2016-10-17 2 views
1

У меня есть большая база кода C#, в которой я пытаюсь реорганизовать и очистить чужой запутанный код. Недавно я наткнулся на такой кусок:Статически обнаруживать несоответствия типов в инструкции foreach

List<Bar> bars = ... ; 

... 

foreach (Foo foo in bars) { ... } 

... 

public class Bar 
{ 
    ... 

    public static explicit operator Foo() { ... } 
} 

Этот тип несоответствия является проблемой. И, как и следовало ожидать, код не фактически работает: это ошибка, которая давно скрывается на виду.

Однако код legal. Ни Visual Studio 2013, ни ReSharper 2016 не жалуются на эту довольно очевидную ошибку: мне пришлось подождать, пока исключение во время выполнения не обнаружит, что код сломан. Я бы скорее узнал намного раньше.

Я искал как Visual Studio, так и опции ReSharper, пытаясь найти способ заставить мои инструменты обнаруживать такие типы несоответствий типов: «Шаблоны кода» ReSharper являются ближайшими, которые я могу получить, и хотя он может распознавать синтаксический шаблон при ошибке, он не поддерживает достаточно глубокий анализ типов, чтобы обнаружить ошибку.

Так кто-нибудь знает способ сделать ReSharper статически обнаруживать foreach тип несоответствий? Или, альтернативно, кто-нибудь знает инструмент, который может?

Update: Первоначально я опущено, что существует explicit пользовательский оператор литья из Bar в Foo - это explicit, заметьте, не implicit. Существование этого оператора литья, похоже, наносит ущерб способности инструментов обнаружить эту проблему. Я обновил код, чтобы показать поведение.

+0

Какая версия R # вы используете? –

+0

ReShaper 2016.1.2, выпущенный в мае 2016 года, чтобы быть конкретным. –

+0

Ах! Я не видел обновления. Я собирался сказать вам, что не могу воспроизвести проблему, поскольку Resharper эффективно дает мне ошибку времени компиляции, но если есть явное преобразование, то единственный способ, который я вижу, - сначала перебрать фильтрацию, используя, например, list.OfType (). –

ответ

6

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

По-видимому foreach вставляет вызов оператору литья explicit, если таковой имеется.

ReSharper имеет право разрешить это, также как и Visual Studio. Вроде. (Лично я до сих пор думаю, что ReSharper должен предупредить об этом, даже если это законно.)

Пар хороших цитат из г Липпертого, объясняя это:

Ответ: семантика цикла Еогеаспа были разработаны до того, как на язык были добавлены дженерики ... В мире с дженериками, где подавляющее большинство перечисленных последовательностей теперь статически типизировано, это ошибка. Но это было бы большой разрыв, чтобы удалить его, поэтому мы застряли с ним.

...

Вы можете спросить, почему C# компилятор не выдает предупреждение в современном коде, где используются дженерики. Когда я был в команде компилятора C#, я внедрил такое предупреждение и попробовал его на корпусе кода C# в Microsoft. Количество предупреждений, созданных в правильном коде (где кто-то имел последовательность животных, но знал, что все они были Жирафом) был большим. Предупреждения, которые слишком часто срабатывают в правильном коде, являются плохими предупреждениями, поэтому мы отказались от добавления функции.

(Весь блог проводки можно найти здесь, а так же поучительно, как это разочарование https://ericlippert.com/2013/07/22/why-does-a-foreach-loop-silently-insert-an-explicit-conversion/.)

Смежные вопросы