C# 8 - 枚举上的 CS8605 "Unboxing possibly null value"

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

我在 .csproj 中有一个 <nullable>enable</nullable> 的项目 我遇到了一些奇怪的警告行为。

我有一个遍历枚举的 foreach 语句,枚举中的 foreach 项目运行一些代码。 但是当我尝试这样做时,VS2019 会标记 CS8605“拆箱可能为空值”警告。

此处显示完整代码。错误显示超过 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];
}

我很难理解为什么 t 可能为 null,因为枚举是不可为 null 的。 我想知道,自从 Enum.GetValues returns 类型 Array 以来,这里是否进行了一些隐式转换,这就是问题的根源。 我目前的解决方案只是抑制警告。但我想了解这里发生了什么。也许有更好的方法来迭代枚举。

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.

没错,foreach 循环进行了隐式转换。这就是问题的根源。

如您所见,Enum.GetValues returns 类型为 Array 的对象。 nullable context 启用的 Array 项目是可空类型 object?。当您在 foreach 循环中迭代 Array 时,每个 Array 项都被转换为迭代变量的类型。在您的情况下,object? 类型的每个 Array 项目都被转换为 TextureSet 类型。此转换会产生警告 Unboxing possibly null value.

如果您在 sharplab.io 中尝试您的代码,您会发现在内部 C# 编译器将考虑的 foreach 循环转换为清楚地显示问题的 while 循环(为简单起见我省略了一些代码块):

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.

您也可以使用下一个 approach 修复警告:

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