TL;DR: ошибка говорит о том, что переменная (доказуемо) не назначена -- FALSE. На самом деле, переменная недоказуемо присваивается (используя теоремы доказательства, доступные компилятору).
LINQ разработан с учетом чистых функций... тех, которые возвращают выходные данные на основе входных данных и не имеют побочных эффектов.
Как только это будет переписано, это будет:
roles.Where(r => Enum.TryParse(r, out value)).Select(r => value);
и снова переписал на
Enumerable.Select(Enumerable.Where(roles, r => Enum.TryParse(r, out value)), r => value);
Эти функции LINQ будут вызывать лямбду-фильтр перед любыми вызовами лямбда-выражения, но компилятор не может этого знать (по крайней мере, без анализа потока данных в специальном регистре или между модулями). Более проблематично, если бы для разрешения перегрузки была выбрана другая реализация Where
, то, возможно, лямбда с TryParse
НЕ вызывалась бы.
Правила компилятора для определенного присваивания очень упрощены и ошибочны в сторону безопасности.
Вот еще один пример:
bool flag = Blah();
int value;
if (flag) value = 5;
return flag? value: -1;
Использование неинициализированного значения невозможно, но правила языка для анализа потока данных приводят к ошибке компиляции, когда value
используется без "определенного назначения".
Однако ошибка компилятора сформулирована плохо. Не быть «определенно назначенным» - это не то же самое, что быть определенно «неназначенным», как подразумевается в ошибке.
person
Ben Voigt
schedule
11.03.2015
select 0
. Самым элегантным решением был бы метод расширения TryParse, возвращающий int? - person DasKrümelmonster   schedule 11.03.2015Parse
? Но это вызывает исключение при сбое. Он хочет ноль элементов от каждой ошибки синтаксического анализа и один элемент от каждого успешного синтаксического анализа... что может быть выполнено с помощьюSelectMany
. - person Ben Voigt   schedule 11.03.2015from r in roles let tmp = helpermethod(r) where tmp != null select tmp;
- person DasKrümelmonster   schedule 11.03.2015