2016-09-14 88 views
2

如果您有用於位標誌的enum,即C#Enum.HasFlag對位AND運算符檢查

[Flags] 
internal enum _flagsEnum : byte 
{ 
    None = 0,   //00000000 
    Option1 = 1,  //00000001 
    Option2 = 1 << 1, //00000010 
    Option3 = 1 << 2, //00000100 
    Option4 = 1 << 3, //00001000 
    Option5 = 1 << 4, //00010000 
    Option6 = 1 << 5, //00100000 
    Option7 = 1 << 6, //01000000 
    Option8 = 1 << 7, //10000000 
    All = Byte.MaxValue,//11111111 
} 

_flagsEnum myFlagsEnum = _flagsEnum.None; 

它更快做..

bool hasFlag = myFlagsEnum.HasFlag(_flagsEnum.Option1); 

或做..

bool hasFlag = myFlagsEnum & _flagsEnum.Option1 != 0 

如果檢查多個標誌之間存在性能差異,那麼也考慮到這一點。

通常我會檢查參考源,但在這種情況下,Enum.HasFlags只是去了一個extern InternalHasFlags,所以我不知道它在做什麼。

+2

有一些性能成本。請參閱:http://stackoverflow.com/questions/7368652/what-is-it-that-makes-enum-hasflag-so-slow –

+1

似乎不成熟的優化。我不喜歡'HasFlag',它接受任何'enum'對象作爲參數,而不是一個相同的類型。 –

+1

'HasFlag'不僅僅是一個簡單的按位檢查http://blogs.microsoft.co.il/bnaya/2011/01/28/enumhasflag-good-or-bad/ –

回答

2

使用HasFlag會帶來性能成本,因爲實施將驗證您傳遞的enum值與該標誌的類型相同。

利用這種差異的方式進行,執行高度優化,以避免促進較短類型,例如編byte,到int

switch (pMTThis->GetNumInstanceFieldBytes()) { 
case 1: 
    cmp = ((*(UINT8*)pThis & *(UINT8*)pFlags) == *(UINT8*)pFlags); 
    break; 
case 2: 
    cmp = ((*(UINT16*)pThis & *(UINT16*)pFlags) == *(UINT16*)pFlags); 
    break; 
case 4: 
    cmp = ((*(UINT32*)pThis & *(UINT32*)pFlags) == *(UINT32*)pFlags); 
    break; 
case 8: 
    cmp = ((*(UINT64*)pThis & *(UINT64*)pFlags) == *(UINT64*)pFlags); 
    break; 
default: 
    // should not reach here. 
    UNREACHABLE_MSG("Incorrect Enum Type size!"); 
    break; 
} 

ReflectionEnum::InternalHasFlag源可以發現here

雖然成本相對較高,但除了最極端的情況之外,這是不太可能發生的。我建議保留它,除非您的配置文件指出此次調用是您程序中最大的瓶頸。

+0

啊,是的,我應該考慮檢查現在開放的CLR的來源 - 猜猜我還沒有習慣這個! – Yushatak