Оператор переключения без значения по умолчанию при контакте с перечислениями

exists ключевое слово может использоваться таким образом, но действительно оно предназначается как способ постараться не рассчитывать:

--this statement needs to check the entire table
select count(*) from [table] where ...

--this statement is true as soon as one match is found
exists ( select * from [table] where ... )

Это является самым полезным, где Вы имеете if условные операторы, поскольку exists может быть намного более быстрым, чем count.

Эти in лучше всего используется, где у Вас есть статический список для передачи:

 select * from [table]
 where [field] in (1, 2, 3)

, Когда у Вас есть таблица в in оператор, имеет больше смысла использовать join, но главным образом это не должно иметь значения. Оптимизатор запросов должен возвратить тот же план так или иначе. В некоторых реализациях (главным образом более старый, таких как Microsoft SQL Server 2000) in запросы будут всегда добираться вложенное соединение план, в то время как join запросы будут использовать вложенный, слияние или хеш как соответствующие. Более современные реализации более умны и могут скорректировать план, даже когда in используется.

35
задан Mark 8 July 2009 в 17:59
поделиться

7 ответов

Heck, the situation is far worse than just dealing with enums. We don't even do this for bools!

public class Test {        
  public string GetDecision(bool decision) {
    switch (decision) {
       case true: return "Yes, that's my decision";                
       case false: return "No, that's my decision"; 
    }
  }
}

Produces the same error.

Even if you solved all the problems with enums being able to take on any value, you'd still have this issue. The flow analysis rules of the language simply do not consider switches without defaults to be "exhaustive" of all possible code paths, even when you and I know they are.

I would like very much to fix that, but frankly, we have many higher priorities than fixing this silly little issue, so we've never gotten around to it.

37
ответ дан 27 November 2019 в 06:46
поделиться

Это потому, что значение решение может фактически быть значением, которое не является частью перечисления, например:

string s = GetDecision((Decision)42);

Такого рода вещи не предотвращаются компилятор или CLR. Значение также может быть комбинацией значений перечисления:

string s = GetDecision(Decision.Yes | Decision.No);

(даже если перечисление не имеет атрибута Flags )

Из-за этого вы должны всегда ставить случай по умолчанию при переключении, поскольку вы не можете явно проверить все возможные значения

17
ответ дан 27 November 2019 в 06:46
поделиться

Выбрасывает исключение в предложении default :

default:
    throw new ArgumentOutOfRangeException("decision");

Это гарантирует, что все возможные пути будут покрыты, пока избежание логических ошибок, возникающих в результате добавления нового значения.

15
ответ дан 27 November 2019 в 06:46
поделиться
public enum Decision { Yes, No}

public class Test
{
    public string GetDecision(Decision decision)
    {
        switch (decision)
        {
            case Decision.Yes:
                return "Yes, that's my decision";
            case Decision.No:
                return "No, that's my decision";
            default: throw new Exception(); // raise exception here.

        }
    }
}
7
ответ дан 27 November 2019 в 06:46
поделиться

По умолчанию используется для вашей защиты. Выбросьте исключение из значения по умолчанию, и если кто-нибудь добавит дополнительное перечисление, вы сможете пометить его.

2
ответ дан 27 November 2019 в 06:46
поделиться

Я всегда думаю об этом дефолте как о провале / исключении.

Так что здесь не может быть, а вместо этого будет «Недействительное решение, обратитесь в службу поддержки».

Я не Я не понимаю, как это могло случиться, но это будет случай улова / исключения.

1
ответ дан 27 November 2019 в 06:46
поделиться

В дополнение к случаю, вы можете привести любое int к вашему перечислению и получить перечисление, которое вы не обрабатываете. Также существует случай, когда, если перечисление находится во внешней .dll, и эта .dll обновляется, это не нарушает ваш код, если к перечислению добавляется дополнительная опция (например, Да, Нет, Может быть). Итак, для обработки этих будущих изменений вам также понадобится случай по умолчанию. Невозможно гарантировать во время компиляции, что вы знаете каждое значение, которое enum будет иметь на протяжении всей его жизни.

0
ответ дан 27 November 2019 в 06:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: