Логика метода bool Enum.HasFlag(Enum enum)
В MSDN указано следующее:
bool Enum.HasFlag(Enum enum)
{
return (thisInstance & enum) == enum;
}
Вопрос: зачем сравнивать результат побитового "И" с искомым флагом, если можно было сделать так:
return (thisInstance & enum) != 0;
или так:
return (bool)(thisInstance & enum);//так не работает в С#
Чтобы не было явных/неявных преобразований типов? (но при побитовых операциях все равно происходит неявное преобразование к Int32 или Int64)
Просто вот нигде это не объясняется, а вопрос интересный, потому что во всех примерах (даже ручной реализации HasFlag - везде (thisInstance & enum) == enum ).
Так вот хотел узнать, может там производительность выше за счет каких-то встроенных функций CLR или лучше происходит оптимизация?
В данный момент мы создаем дубликат кода!! (ну если уж вообще говорить)
Ответы (2 шт):
Для начала, то что вы привели - это спецификация, а не реализация. Поэтому любые соображения оптимизации тут не имеют никакого смысла.
Теперь выясним, чем вообще отличаются сравнение с исходным флагом и с нулём. А отличаются они в случае составных флагов:
enum Foo {
A = 1,
B = 2,
C = 4,
}
Foo data = Foo.A | Foo.C;
Foo flag = Foo.A | Foo.B;
bool first = (data & flag) != 0; // true
bool second = (data & flag) == flag; // false
Сравнение с 0 проверяет установлен ли хотя бы один бит, сравнение с флагом проверяет установлены ли все биты.
Итак:
public bool HasFlag (Enum flag);
Returns true if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, false.
То есть, каждому биту, равному 1 в flag должен соответствовать бит 1 в current instance. Current instance может иметь дополнительные биты, равные 1, они не влияют на результат. Отсюда: thisInstance & flag должно быть равно flag.
Пример, для упрощения 8 бит. thisInstance = 11000011, flag = 11000000. Результат должен быть true, т.к. каждой единице в flag соответствует единица в thisInstance.
thisInstance & flag = 11000000, то есть равно flag.