Dot-Net

.NET:為什麼不檢查列舉的範圍/值?

  • January 3, 2022

這一直困擾著我。也許對 .NET 內部有一些核心知識的人可以向我解釋一下。

假設我定義一個列舉如下:

public enum Foo
{
  Eenie = 1,
  Meenie = 2,
  Miney = 3,
  Moe = 4
}

現在,還假設在我的程式碼中的某處,我有以下程式碼:

int bar = (Foo)5;

這將編譯得很好,並且不會引發任何異常,即使值 5 顯然不是Foo.

或者,考慮以下幾點:

public void ProcessFoo(Foo theFoo)
{
   // Do processing
}

public static void Main()
{
   ProcessFoo((Foo)5);
}

同樣,也不例外。

在我看來,這應該會導致類型不匹配異常,因為 5 不是Foo. 但設計師選擇不這樣做。

現在,我編寫了一個擴展方法,可以驗證是否是這種情況,呼叫它來確保是這種情況並沒有什麼大不了的,但我必須使用反射來做到這一點(所有的性能損失等等)。

再說一遍,有什麼令人信服的理由可能促使決定不檢查列舉?

作為參考,來自Enum 類的 MSDN 文件

當您定義將列舉常量作為值的方法或屬性時,請考慮驗證該值。原因是您可以將數值轉換為列舉類型,即使該數值未在列舉中定義。

問題是性能。對普通列舉(例如 Color)進行檢查列舉非常簡單

enum Color {
 Red,
 Blue
}

但問題在於用作位標誌的列舉。

enum Property {
 IsFirst = 0x1,
 IsDefault = 0x2,
 IsLastAccessed = 0x4
}

必須對轉換為 Enum 值的每個整數進行按位檢查被認為過於昂貴。因此,輕鬆轉換為列舉值。

範圍檢查可能會產生不必要的成本。因此,不隱式執行它是合理的。如前所述,[Flags]要求不進行此類檢查。如果執行時會檢查是否存在[Flags],則每次執行轉換時仍會導致執行時損失。

解決這個問題的唯一方法是讓編譯器知道該[Flags]屬性。我想這樣做並不是為了減少硬編碼到編譯器中的執行時知識量。

引用自:https://stackoverflow.com/questions/432937