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

1

5

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.

Ancheta answered 18/5, 2011 at 22:19 Comment(4)
Are you using resultingThing in the else case?Drove
No not using resultingThing in the else. Also, initializing it to null gets rid of the compiler error as expected.Ancheta
Not really ideal, but try initializing resultingThing using the default keyword, i.e. default(IThing). For reference types, this should be null; for value types, it should be the equivalent of a default-constructed type.Marbleize
I have reduced the error case, the iterator block has no influence, though the use of dynamic is relevant, see my updated answer.Fosterfosterage
F
1

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

Fosterfosterage answered 18/5, 2011 at 22:34 Comment(2)
You didn't say whether your version was tested with the Microsoft C# compiler. So I tried it, and it does, in fact, produce the error given in the question title.Provence
Yes, it was the Microsoft compiler. It looks like it is indeed a bug.Ancheta

© 2022 - 2024 — McMap. All rights reserved.