Search code examples
c#.net-coreenumsc#-8.0nullable-reference-types

C# 8 - CS8605 "Unboxing possibly null value" on enum


I have a project with <nullable>enable</nullable> in the .csproj and I am experiencing some weird behavior of the warnings.

I have a foreach statement that iterates over an enum, and foreach item in the enum runs some code. But VS2019 flags up the CS8605 "Unboxing possibly null value" warning when I try and do this.

enter image description here

Full code is shown here. The error displays over the deceleration of t.

public static class Textures
{
    private static readonly Dictionary<TextureSet, Texture2D> textureDict = new Dictionary<TextureSet, Texture2D>();

    internal static void LoadContent(ContentManager contentManager)
    {
        foreach(TextureSet t in Enum.GetValues(typeof(TextureSet)))
        {
            textureDict.Add(t, contentManager.Load<Texture2D>(@"textures/" + t.ToString()));
        }
    }

    public static Texture2D Map(TextureSet texture) => textureDict[texture];
}

I'm struggling to understand why there is potential for t to be null as enums are non-nullable. I'm wondering if, since Enum.GetValues returns of type Array if there is some implicit casting going on here that is the root of this problem. My solution currently is just to suppress the warning. But I would like to understand what's going on here. Perhaps there is better way to iterate over an enum.


Solution

  • I'm wandering if, since Enum.GetValues returns of type Array if there is some implicit casting going on here that is the root of this problem.

    You are right, there is an implicit casting that is made by the foreach loop. And it is the root of the problem.

    As you've noted Enum.GetValues returns an object of type Array. With nullable context enabled items of the Array are of nullable type object?. When you iterate over an Array in a foreach loop each Array item is casted to the type of the iteration variable. In your case each Array item of type object? is casted to the type TextureSet. This cast produces the warning Unboxing possibly null value.

    If you try your code in sharplab.io you'll see that internally C# compiler transforms considered foreach loop to the while loop that clearly shows the problem (some code blocks I ommited for simplicity):

    IEnumerator enumerator = Enum.GetValues(typeof(TextureSet)).GetEnumerator();
    while (enumerator.MoveNext())
    {
        // Type of the enumerator.Current is object?, so the next line
        // casts object? to TextureSet. Such cast produces warning
        // CS8605 "Unboxing possibly null value".
        TextureSet t = (TextureSet) enumerator.Current;
    }
    

    My solution currently is just to suppress the warning. ... Perhaps there is better way to iterate over an enum.

    Also you can use the next approach to fix the warning:

    foreach (TextureSet t in (TextureSet[]) Enum.GetValues(typeof(TextureSet)))
    {
    }