# [C#] `const` vs `readonly`
###### tags: `C#` `Programming`
## `const`
- **編譯時期**常數
- 只能用於primitive type或refernce type
- 只能在宣告時賦值
- 在class內,被視為靜態成員(static member)
## `readonly`
- **執行時期**常數
- 只能在宣告時賦值或利用建構子(Contructor)
- 與`const`比較,`readonly`修飾完依然是一般成員(member variable)
## 實驗
==使用VS2019==
### 第一步 - 新增專案
1. 新增一個ConsoleApp(圖1)

2. 對該專案的Solution新增一個Library,中文會叫做「程式庫」(圖2)


3. 新增對程式庫的相依性(新增Reference) (圖3)

### 第二步 - 建置
Lib
```csharp=
namespace ExampleLib
{
public class Constant
{
public static readonly string ReadOnlyString = "Readonly 1";
public const string ConstString = "Const 1";
}
}
```
ConsoleApp
```csharp=
using System;
using ExampleLib;
namespace Example
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"{Constant.ReadOnlyString}");
Console.WriteLine($"{Constant.ConstString}");
Console.ReadKey();
}
}
}
```
建置輸出後,沒意外會出現
```tiddlywiki=
Readonly 1
Const 1
```
### 第三步 - 更新
#### 檔案總管
把ConsoleApp的檔案總管打開後,會看到 (圖4):

兩個主要的檔案,一個是執行檔(.exe),另一個程式庫(.dll)
再來更新我們**程式庫(DLL)**
```csharp=
namespace ExampleLib
{
public class Constant
{
public static readonly string ReadOnlyString = "Readonly 2";
public const string ConstString = "Const 2";
}
}
```
:::warning
:warning: 記得只要更新程式庫,不要直接按`F5`全部都建置了
:::
然後回到ConsoleApp的資料夾,把程式庫建置出來的元件全部複製一份,複製到ConsoleApp的資料夾裡。
之後再次打開執行檔,會發現`readonly`跟著程式庫更新了,但`const`沒有
```tiddlywiki=
Readonly 2
Const 1
```
這就是上面所說的**編譯時期常數**和**執行時期常數**
## 結論
- 建議使用執行期常數(static readonly),而非編譯期常數(const)。
## 參考資料
- [const vs readonly](https://dotblogs.com.tw/bda605/2019/06/30/223857)
- [C# - const vs static readonly](https://blog.johnwu.cc/article/c-sharp-const-vs-static-readonly.html)
- [const 和 readonly 特性與使用時機](https://ronsun.github.io/content/20180519-const-vs-readonly.html)