Почему компилятор C # утверждает, что «использование неназначенной переменной» предшествует «выходному возврату» и является динамическим?

#dynamic #c#-4.0 #yield-keyword #out-parameters

#динамический #c #-4.0 #yield-ключевое слово #out-parameters

Вопрос:

Компилятор жалуется, что resultingThing в приведенном ниже коде используется перед назначением.

 private IEnumerable<IThing> FindThings(dynamic spec)
{
    if (spec == null)
        yield break;

    IThing resultingThing;
    if (spec.Something > 0 amp;amp; dictionary.TryGetValue(spec.Something, out resultingThing))
        yield return resultingThing;
    else
        // ...
}
  

Почему он утверждает это?

Я пробовал другую версию метода, в которой нет использования yield (например, просто return IEnumerable<IThing> ), но с параметром dynamic, и я пробовал версию метода, в которой не передается dynamic (т. Е. то, что мы делали в предыдущих версиях C #). Они компилируются.

Комментарии:

1. Используете ли вы resultingThing в else случае?

2. Нет, не используется resultingThing в else . Кроме того, инициализация его в null избавляет от ошибки компилятора, как и ожидалось.

3. Не совсем идеально, но попробуйте инициализировать, resultingThing используя default ключевое слово, т. Е. default(IThing) . Для ссылочных типов это должно быть null ; для типов значений это должно быть эквивалентом типа, созданного по умолчанию.

4. Я уменьшил случай ошибки, блок итератора не оказывает никакого влияния, хотя использование dynamic имеет значение, см. Мой обновленный ответ.

Ответ №1:

Похоже, что это ошибка компилятора (или ограничение, если хотите).

Я сократил минимальный случай сбоя до:

 static private IThing FindThings(dynamic spec)
{
    IThing resultingThing;
    if ((null!=spec) amp;amp; dictionary.TryGetValue(spec, out resultingThing))
        return resultingThing;
return null;
}
  

Что дает ту же самую диагностику компилятора, без использования поиска элементов в dynamics или блоков итератора.

Для справки, компилятор mono не использует это:

 using System;
using System.Collections.Generic;

public static class X
{
    public interface IThing { }

    private static readonly IDictionary<string, IThing> dictionary = new Dictionary<string, IThing>();

    static private IThing FindThings(dynamic spec)
    {
        IThing resultingThing;
        if ((null!=spec) amp;amp; dictionary.TryGetValue(spec, out resultingThing))
            return resultingThing;
        return null;
    }

    public static void Main(string[] s)
    {

    }
}
  

Компиляция этого:

 dmcs -v -warnaserror -warn:4 t.cs
  

Никаких предупреждений

Комментарии:

1. Вы не сказали, была ли ваша версия протестирована с помощью компилятора Microsoft C #. Итак, я попробовал это, и это действительно приводит к ошибке, указанной в названии вопроса.

2. Да, это был компилятор Microsoft. Похоже, что это действительно ошибка.