Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the C# compiler claiming 'use of an unassigned variable' prior to 'yield return' and dynamic?

The compiler complains that resultingThing in the code below is being used before being assigned to.

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

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

Why does it claim this?

I have tried a different version of the method in which there are no yield usages (e.g. just return IEnumerable<IThing>) but with the dynamic parameter, and I have tried a version of the method in which dynamic is not passed in (i.e. what we've done in prior versions of C#). These compile.

like image 312
Kit Avatar asked Nov 13 '22 23:11

Kit


1 Answers

I appears to be a compiler bug (or limitation, if you prefer).

I reduced the minimal failing case to:

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

Which gives the same compiler diagnostic, without involving member lookup on dynamics, nor iterator blocks.

For reference the mono compiler does not trip over that:

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) && dictionary.TryGetValue(spec, out resultingThing))
            return resultingThing;
        return null;
    }

    public static void Main(string[] s)
    {

    }
}

Compiling that:

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

No warnings

like image 104
sehe Avatar answered Dec 26 '22 02:12

sehe