這天小明來問甚麼是 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 = 1
ReadonlyString = 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 = 1
ReadonlyString = 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 , 每個物件都寫成如下
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();
}
}