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}"); }}
这支 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";}
大部分的人都会回答 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 建议的使用时机大概有以下情况:
接着回答小明的第二个问题 "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(); }}