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];
}
}

通过静态字段来维护这样一个状态,确实显得很有技巧。因为我从来不这么做,所以我觉得有点惊讶。当然,这并不代表这种实现方式不好。我的疑问有如下几点:

  1. 已打开设备列表并不属于装饰类的功能/概念,设备列表属于整个App或串口管理中心或者作其他逻辑概念。
  2. 只能提供打开过或者注册过的串口列表,而不能提供未打开的串口列表,即使这些串口列表是存在的。如果需要查看枚举串口,显然做不到。
  3. 如果外部需要知道当前的设备列表,通过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 字段来维护状态是不是一个好主意的更多相关文章

  1. IOS的变量前加extern和static字段

    IOS的变量前加extern和static字段 前一阵子,做项目的时候到网上找Demo,打开运行的时候发现其中变量前有关键字extern和static,所以我研究了一下子 对于extern来说可以理解 ...

  2. Elasticsearch 关键字:索引,类型,字段,索引状态,mapping,文档

    1. 索引(_index)索引:说的就是数据库的名字.我这个说法是对应到咱经常使用的数据库. 结合es的插件 head 来看. 可以看到,我这个地方,就有这么几个索引,索引就是数据库,后面是这个数据库 ...

  3. readonly 只读字段的初始化值确定|static 字段的初始值确定

    类的初始化顺序 如下: 第一次实例化Son============================ C#编译器缺省将每一个成员变量初始化为他的默认值Son静态字段Son静态构造函数Son字段Fathe ...

  4. 英雄联盟网络测速 v1.3 全服全区取延时+取服务器维护状态+机房地理位置

    全服全区取延时+取服务器维护状态+机房地理位置 v1.2修复了服务器状态获取不准确的bug 下载链接: https://pan.baidu.com/s/1c1LHIY8 

  5. cassandra——可以预料的查询,如果你的查询条件有一个是根据索引查询,那其它非索引非主键字段,可以通过加一个ALLOW FILTERING来过滤实现

    cassandra的索引查询和排序 转自:http://zhaoyanblog.com/archives/499.html   cassandra的索引查询和排序 cassandra的查询虽然很弱,但 ...

  6. mysql统计一个字段的多种状态

    假如我有下面的表:ID    Item           status            updatetime    author1    a        1        2014-01-0 ...

  7. 一个static和面试官扯了一个小时,舌战加强版

    一:背景 1. 讲故事 最近也是奇怪,在社区里看到好几篇文章聊static 的玩法以及怎么拿这个和面试官扯半个小时,有点意思,点进去看都是java版的,这就没意思了,怎么也得有一篇和面试官扯C# 中的 ...

  8. MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现

    1. 问题描述 在使用MyBatis,我们经常会遇到这种情况:SELECT两个字段,需要返回一个Map,其中第一个字段作为key,第二个字段作为value.MyBatis的MapKey虽然很实用,但并 ...

  9. 使用python+django+twistd 开发自己的操作和维护系统的一个

    许多开源操作系统和维护系统,例nagios.zabbix.cati等等,但是,当他们得到的时间自己的个性化操作和维护需求,始终无力! 最近的一项研究python.因此,我们认为python+djang ...

随机推荐

  1. noip模拟赛 站军姿

    分析:纯数学题.相离和包含关系的可以很容易算出来答案,相交的话要先求出两个圆的面积,然后减掉中间重叠的部分,这一部分并不能直接求出来,但是可以求出两个扇形的面积,和它们围成的一个四边形的面积,加加减减 ...

  2. 最小生成树prime算法模板

    #include<stdio.h> #include<string.h> using namespace std; int map[505][505]; int v, e; i ...

  3. 了解一下JAVA中的NIO模块

    网上资料大把,但要写写代码,我这个年纪的人才有一点点记忆了.. 参考URL: http://blog.csdn.net/wuxianglong/article/details/6612282 pack ...

  4. ZooKeeper可视化Web管理工具收集(待实践)

    原来ZooKeeper是有Web管理后台的.但是仅限于操作ZooKeeper的数据,如果要监控性能,估计要借助Nagios去配合. 这些工具应该ZK UI最好用,下面是收集的一些工具安装教程: htt ...

  5. HDU 5431

    由于最长不超过30个字符(由K的范围确定),于是,枚举所有的字符串,二分中使用二分就可以确定第K小了. #include <iostream> #include <cstdio> ...

  6. I NEED A OFFER! (hdu 1203 01背包)

    I NEED A OFFER! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  7. ASP.NET—016:ASP.NET中保存文件对话框

    本想在asp.net中使用savediallog保存文件,结果提示:当应用程序不是以 UserInteractive 模式执行时显示模式对话框或窗口是无效操作. 在ASP.NET中使用例如以下方式.保 ...

  8. CodeForces 444C. DZY Loves Physics(枚举+水题)

    转载请注明出处:http://blog.csdn.net/u012860063/article/details/37509207 题目链接:http://codeforces.com/contest/ ...

  9. 2014百度之星第二题Disk Schedule(双调欧几里得旅行商问题+DP)

    Disk Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  10. light oj1074

    Description The people of Mohammadpur have decided to paint each of their houses red, green, or blue ...