通过Static 字段来维护状态是不是一个好主意
static是申明静态字段、静态方法或者静态类的修饰符。使用static申明的字段属于类型本身而不属于任何字段,声明的类也具有一些特别特性,比如不能实例化,不能继承等。用通俗化的语言来说,static字段即使创建多个类型实例也只会声明一次,应为它属于类型。它在所有类实例之间皆可访问,可以认为静态字段是类型的全局变量。
我会在一些场景下使用static字段,出现次数最多的就是作为函数/方法修饰符或者简单的单例模式。我个人认为,static函数类似于C函数(method),而一般中function称呼实例方法。静态函数与实例无关,更多的体现出一种无关联性。在字段(property)上,就很少使用static修饰符了。除非内部实例需要临时计数,或者具有无状态的其他类型的实例对象字段。
最近考虑到设计一个串口通信的装饰类(基于SerialPort, System.IO.Port),用来扩充SerialPort的功能,比如帧完整性检查、超时检测与重传等。在我开始工作之前,已经有了一些基本实现。先不关注装饰器的功能,该类通过简单工厂函数来创建实例,并在内部维护了基于名字的实例列表。在每次打开一个串口后,会在列表中以<Key,Value>的形式登记一下,在内存中维护了一个打开过串口的设备列表。
public class SerialPortDecorator : IDisposable
{
static public Dictionary<string, SerialConn> _PortDict = new Dictionary<string, SerialConn>();
private SerialPort _SerialPort = null; /// <summary>
/// Class for Serial Connection to a Comm port.
/// </summary>
/// <remarks>
/// This class should be thread safe and non blocking. It has two modes, one where
/// a reply is expected (will callback a delegate with response) and one where no
/// reply is expected. More complex handling of reply and expected response is handled
/// by the caller.
/// </remarks>
/// <param name="portNameIn"></param>
/// <returns></returns>
public static SerialConn GetSerialConn(string portNameIn)
{
lock (_StaticLockObj)
{
// TODO validate the portname
if (!_PortDict.ContainsKey(portNameIn))
{
SerialConn sc = new SerialConn();
sc.Initialize(portNameIn);
_PortDict.Add(portNameIn, sc);
} return _PortDict[portNameIn];
}
}
通过静态字段来维护这样一个状态,确实显得很有技巧。因为我从来不这么做,所以我觉得有点惊讶。当然,这并不代表这种实现方式不好。我的疑问有如下几点:
- 已打开设备列表并不属于装饰类的功能/概念,设备列表属于整个App或串口管理中心或者作其他逻辑概念。
- 只能提供打开过或者注册过的串口列表,而不能提供未打开的串口列表,即使这些串口列表是存在的。如果需要查看枚举串口,显然做不到。
- 如果外部需要知道当前的设备列表,通过SerialPortDecorator._PortDict来达到目的实在太奇怪。
在MSDN C#编程指南中,有一段static的示例代码:
/***为了说明静态成员,请看一个表示公司雇员的类。 假设该类包含一种对雇员计数的方法和一个存储雇员数的字段。 该方法和字段都不属于任何实例雇员, 而是属于公司类。 因此,应该将它们声明为此类的静态成员。
示例
此示例读取新雇员的姓名和 ID,将雇员计数器加一,并显示新雇员的信息和新的雇员数。 为简单起见,该程序从键盘读取当前的雇员数。 在实际的应用中,应从文件读取此信息。
C#
***/
public class Employee4
{
public string id;
public string name; public Employee4()
{
} public Employee4(string name, string id)
{
this.name = name;
this.id = id;
} public static int employeeCounter; public static int AddEmployee()
{
return ++employeeCounter;
}
}
“该方法和字段都不属于任何实例雇员, 而是属于公司类。”这句话就指出了static字段的语义。基于此,对于疑问1不置可否。
关于疑问2,枚举未连接串口列表很明显属于不同的语义。使用static字段无法提供这些内容,这些内容也不适合放在装饰类中。提出来,只是为了说明需求环境。如果真的有如此需求,static字段很明显不适合。在一定程度上指出了static的应用场景——语义单一、明确。
疑问3就很重要了。在上面的MSDN示例中,静态字段employeeCounter只是为了生成增序ID。虽然属于公司,但只为员工编号服务。现实应用中并不会通过查询该ID来查询员工数量,一般只会用在批量环境或者查询结果中生成序列ID。从此示例来看,我觉得static 字段的应用范围应该限制在包含它的类上。
对于疑问1,2,3的讨论,我想说static字段的应用场景和能力具有语义限制。static字段在语义上不属于当前类,属于当前名词的匿名拥有者。在使用上,最好只在其拥有类中进行使用,不用超过类范围。
这只是我个人的看法。
通过Static 字段来维护状态是不是一个好主意的更多相关文章
- IOS的变量前加extern和static字段
IOS的变量前加extern和static字段 前一阵子,做项目的时候到网上找Demo,打开运行的时候发现其中变量前有关键字extern和static,所以我研究了一下子 对于extern来说可以理解 ...
- Elasticsearch 关键字:索引,类型,字段,索引状态,mapping,文档
1. 索引(_index)索引:说的就是数据库的名字.我这个说法是对应到咱经常使用的数据库. 结合es的插件 head 来看. 可以看到,我这个地方,就有这么几个索引,索引就是数据库,后面是这个数据库 ...
- readonly 只读字段的初始化值确定|static 字段的初始值确定
类的初始化顺序 如下: 第一次实例化Son============================ C#编译器缺省将每一个成员变量初始化为他的默认值Son静态字段Son静态构造函数Son字段Fathe ...
- 英雄联盟网络测速 v1.3 全服全区取延时+取服务器维护状态+机房地理位置
全服全区取延时+取服务器维护状态+机房地理位置 v1.2修复了服务器状态获取不准确的bug 下载链接: https://pan.baidu.com/s/1c1LHIY8
- cassandra——可以预料的查询,如果你的查询条件有一个是根据索引查询,那其它非索引非主键字段,可以通过加一个ALLOW FILTERING来过滤实现
cassandra的索引查询和排序 转自:http://zhaoyanblog.com/archives/499.html cassandra的索引查询和排序 cassandra的查询虽然很弱,但 ...
- mysql统计一个字段的多种状态
假如我有下面的表:ID Item status updatetime author1 a 1 2014-01-0 ...
- 一个static和面试官扯了一个小时,舌战加强版
一:背景 1. 讲故事 最近也是奇怪,在社区里看到好几篇文章聊static 的玩法以及怎么拿这个和面试官扯半个小时,有点意思,点进去看都是java版的,这就没意思了,怎么也得有一篇和面试官扯C# 中的 ...
- MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现
1. 问题描述 在使用MyBatis,我们经常会遇到这种情况:SELECT两个字段,需要返回一个Map,其中第一个字段作为key,第二个字段作为value.MyBatis的MapKey虽然很实用,但并 ...
- 使用python+django+twistd 开发自己的操作和维护系统的一个
许多开源操作系统和维护系统,例nagios.zabbix.cati等等,但是,当他们得到的时间自己的个性化操作和维护需求,始终无力! 最近的一项研究python.因此,我们认为python+djang ...
随机推荐
- Android第三方文件选择器:aFileChooser
Android第三方文件选择器:aFileChooser aFileChooser是Android平台上的一个第三方文件选择器,其在github上的项目主页是:https://github.co ...
- 火星人 2004年NOIP全国联赛普及组
题目描述 Description 人类终于登上了火星的土地并且见到了神秘的火星人.人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法.这种交流方法是这样的,首先,火星人把一个 ...
- const关键字作用
const int a; int const a; const int *a; int * const a; int const * a const; /******/ 前两个的作用是一样,a是一个常 ...
- 【ACM】nyoj_132_最长回文子串_201308151713
最长回文子串 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 输入一个字符串,求出其中最长的回文子串.子串的含义是:在原串连续出现的字符串片段.回文的含义是:正着看和 ...
- [转]十五天精通WCF——第七天 Close和Abort到底该怎么用才对得起观众
一:文起缘由 写这一篇的目的源自于最近看同事在写wcf的时候,用特别感觉繁琐而且云里雾里的嵌套try catch来防止client抛出异常,特别感觉奇怪,就比如下面的代码. public void S ...
- post and get
POST和GET是Web编程中的两个术语,他们是通过URI访问resource的两种方式.简单的说, GET 是把要访问的资源嵌入在URI中. 假设你在一个页面 http://www.myphone. ...
- java 执行可执行文件时提示“could not find or load main class ”的问题
- Supervisor-进程监控自动重启
Supervisor是一个进程监控程序. 需求一:我现在有一个进程需要每时每刻不断的跑,但是这个进程又有可能由于各种原因有可能中断.当进程中断的时候我希望能自动重新启动它,此时,我就需要使用到了Sup ...
- Extjs grid 设置行字体颜色
CustSuppGrid = Ext.create('Ext.grid.Panel', { title : '', // 标题头 iconCls : 'icon-grid', // 标题图标 stor ...
- luogu1063 能量项链
题目大意 有一串项链,项链上的每个珠子有首尾两个数字,首尾相连的两个珠子的尾数字和头数字相同.每次选择相连的一对珠子,得到第一个项链的首数字*第一个项链的尾数字(第二个项链的首数字)*第二个项链的尾数 ...