static vs const vs singleton 问题

static vs const vs singleton 问题

这天小明来问甚么是 static , 甚么时候该用 static ? const 跟 static readonly 有什么差别 ?

首先我们建立一个 DLL Project, 叫做 Example.dll

public class Example{   public const string ConstString = "1";   public static readonly string ReadonlyString = "1";}

接着我们建立一个 Console Project, 叫做 Hello.exe,

class Program{    static void Main(string[] args)    {        Console.WriteLine($"ConstString = {Example.ConstString}");        Console.WriteLine($"ReadonlyString = {Example.ReadonlyString}");    }}

http://img2.58codes.com/2024/20119139F8w2UweDSP.png

这支 Hello.exe 引用参考 Example.dll , (不要直接参考 Example.csproj 专案) , 没有意外的话, Output 结果应该如下

ConstString = 1ReadonlyString = 1

但现在我们再一次修改 Example.cs , 并重新发布 Example.dll 给 Hello.exe 用

public class Example{   public const string ConstString = "2";   public static readonly string ReadonlyString = "2";}

http://img2.58codes.com/2024/20119139NgT2RqFfzF.png

大部分的人都会回答 Output 都是 2 , 但却落入一个陷阱, 程式依然能正常执行,但 Output 实际上结果会是如下

ConstString = 1ReadonlyString = 2

这是因为 Hello.exe 在第一次被编译时,就已经把所有用到 const 的内容带入其中,没有重新编译的情况下,const 的内容都不会改变。
上述的 Hello.exe 内容会被 Compiler 编译成如下的 IL 中继语言程式码

class Program{    static void Main(string[] args)    {        Console.WriteLine($"ConstString = 1");        Console.WriteLine($"ReadonlyString = {Example.ReadonlyString}");    }}

static readonly 是比较建议的常数使用方法.
而 const 建议的使用时机大概有以下情况:

内容必须要在编译时期决定的时候永远不会改变的内容, 例如能量守恆定律(像是圆周率3.141592, 身分证验证规则)非常需要效能的时候

接着回答小明的第二个问题 "Static vs Singleton 的区别是什么?"

首先小明很喜欢每次建立新的物件的时候, 甚至每一个方法, 通通都宣告 static , 每个物件都写成如下

public static class StaticSampleClass{   public static void SayHello()   {   }   public static void Test1()   {   }}

因为小明认为在程式呼叫端, 只需要一行程式码,

StaticSampleClass.SayHello(); 

不必进行 new 指令, 写起来比较爽快

var obj = new StaticSampleClass();obj.SayHello();

首先 static class and static method 有几个问题

无谓地佔住记忆体不放, 无论应用程式有没有用到的, 都会在应用程式启动的时候初始化测试不容易, 因为直接耦合, 无法进行单元测试无法享用物件导向设计的好处(继承的重用与扩充、介面的可抽换性)

小明就马上把 StaticSampleClass 里面所有方法 method , 都把 static 关键字拔掉,
又尝试加上

public static StaticSampleClass Instance = new StaticSampleClass();

小明完整的程式码如下

public class StaticSampleClass{   public static StaticSampleClass Instance = new StaticSampleClass();   public void SayHello()   {   }   public void Test1()   {   }}

而小明的呼叫端也改成如下

StaticSampleClass.Instance.SayHello();

看来看去也没有比较好呼叫使用, 而且

无论应用程式有没有用到的, 都会在应用程式启动的时候初始化

而 Singleton是一种设计模式,可确保您的应用程序只建立一个实例.

public interface ISample{  void SayHello();  void Test1();}public class SingletonSampleClass : ISample{  public void SayHello()  {  }  public void Test1()  {  }}

另一方面,很多语言都有提供 DI 以及 IOC 框架,这些框架可以帮你建立实例,
只要预先写好物件的interface 即可。同时还可以帮你解决 Singleton 要做的事情,可以不用自己实作 。

可以在应用程式注册之后, 只有当应用程式真正的需要此物件的时候再进行实例化(new).

serviceProvider.AddSingleton<ISample, SingletonSampleClass>();

注册interface 完之后, 呼叫端也只需要简单的一行

public class MyController{   public MyController(ISample sample)   {     sample.SayHello();   }}

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章