C# 8 - 枚举上的 CS8605“取消装箱可能为空值”

JR *_*gan 6 c# enums c#-8.0 nullable-reference-types

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

我有一个遍历枚举的 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];
}
Run Code Online (Sandbox Code Playgroud)

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

我正在使用 .net Core 3.1 和 Visual Studio 社区 2019 16.7.2

Ili*_*hev 7

我什么,因为徘徊Enum.GetValues类型的回报Array,如果有一些隐式转换怎么回事,它是此问题的根源。

你是对的,有一个由 foreach 循环进行的隐式转换。而这正是问题的根源。

正如您所指出的,Enum.GetValues返回一个类型为 的对象Array。随着nullable context的启动项目Array是空类型object?。当您Array在 foreach 循环中迭代时,每个Array项目都被强制转换为迭代变量的类型。在您的情况下,每个Arraytype 项都object?被转换为 type 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;
}
Run Code Online (Sandbox Code Playgroud)

我目前的解决方案只是抑制警告。...也许有更好的方法来迭代枚举。

您也可以使用下一种方法来修复警告:

foreach (TextureSet t in (TextureSet[]) Enum.GetValues(typeof(TextureSet)))
{
}
Run Code Online (Sandbox Code Playgroud)