Запутанный единственный оператор And & и как записать его в базу данных - PullRequest
0 голосов
/ 27 марта 2020

Итак, я где-то видел эту логику c, и я запутался с ней. Почему приведенный ниже код возвращает false? Самое простое объяснение этому и сингл и / или | оператор для манекенов ??

enum Colors{
    yellow,
    red,
    blue,
    green
}

var requestedColor = Colors.yellow;
var matchedColor = Colors.red | Colors.blue;

var result = (requestedColor & matchedColor ) == matchedColor ;

Другое дело, что ранее в базе данных может быть только одно значение requiredColor. скажем, я хочу изменить и записать его как значение matchedColor в базе данных, что будет лучшим способом?

1 Ответ

0 голосов
/ 27 марта 2020

Перечисление - это просто представление целого числа, поэтому здесь мы имеем по умолчанию:

yellow = 0    
red = 1    
blue = 2    
green = 3

, если мы рассмотрим это в двоичном виде, его

yellow = 0000    
red =    0001    
blue =   0010    
green =  0011

единственный | и & известны как побитовые 'или' и 'и'. Они выполняют эти операции по одному биту за раз, поэтому

Colors.red | Colors.blue

равно 0001 | 0010, то есть 0011 (зеленый)

колес, скажем

Colors.red & Colors.blue

будет 0000 (желтый).

Это почти наверняка не то, что вы хотите. Вы используете соглашение enum flags, но чтобы сделать это, вам нужно точно установить ваши значения (заметьте, я изменил capitilization, чтобы следовать обычным соглашениям):

enum Colors{
    Yellow  = 1,
    Red = 2,
    Blue = 4,
    Green = 8
}

В терминах битов это дает:

Yellow = 0001    
Red =    0010    
Blue =   0100    
Green =  1000

Это означает, что каждый цвет имеет свой уникальный бит. Теперь, когда мы делаем

Colors.Red | Colors.Blue

, мы получаем 0010 | 0100, давая 0110. Это не один цвет, а красный и синий вместе взятые. (Обратите внимание, что не комбинированный пурпурный цвет - это просто сохранение обоих цветов в виде группы вместе в одной переменной.) В одной переменной можно сохранить столько цветов, сколько вам нужно.

Тогда мы можем используйте &, чтобы проверить, есть ли цвет в группе:

var requestedColor = Colors.Yellow;
var matchedColor = Colors.Red | Colors.Rlue;

var result = (requestedColor & matchedColor ) != 0 ; // Note, the original code was wrong here we shouldn't compare with matchedColor

Так что requestColor равно 0110 и matchedColor 0001. 0110 & 0001 дает 0000, который не равен нулю, поэтому мы получаем false - желтый не найден в группе.

С другой стороны, если требуемый цвет был красным (0010), то requestedColor & matchedColor равно 0110 & 0010, что дает 0010, что не равно нулю, поэтому мы получаем истину. Красный в группе.

И последнее. Когда вы используете перечисление для этой цели, лучше всего указать его атрибутом, специально разработанным для этой цели, чтобы компилятор мог правильно генерировать строковые представления группы, поэтому правильный код -

[Flags]
enum Colors{
    Yellow  = 1,
    Red = 2,
    Blue = 4,
    Green = 8
}

var requestedColor = Colors.Yellow;
var matchedColor = Colors.Red | Colors.Blue;

var result = (requestedColor & matchedColor) != 0;

Что касается хранения в базе данных, просто сохраните его как целое число и приведите обратно к enum при извлечении.

...