问题描述
我在.csproj中有一个带有<nullable>enable</nullable>
的项目
并且我正在经历一些奇怪的警告行为。
我有一个遍历枚举的foreach语句,并且枚举中的foreach项运行一些代码。 但是,当我尝试执行此操作时,VS2019会标记CS8605“取消装箱可能为空值”警告。
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的原因,因为枚举不可为空。
我想知道,由于Enum.GetValues
返回的类型为Array
,这里是否存在隐式强制转换,这是此问题的根源。
我目前的解决方案只是抑制警告。但是我想了解这里发生了什么。也许有更好的方法来遍历枚举。
我正在使用.net Core 3.1和Visual Studio Community 2019 16.7.2
解决方法
我是否在流连忘返,因为如果有
Enum.GetValues
返回类型为Array
是在这里进行一些隐式转换,这是此操作的根源 问题。
是的,由foreach循环进行了隐式转换。这是问题的根源。
您已经注意到Enum.GetValues
返回类型为Array
的对象。在启用nullable context
的情况下,Array
的项目为可空类型object?
。在foreach循环中遍历Array
时,每个Array
项目都将转换为迭代变量的类型。在您的情况下,类型Array
的每个object?
项目都强制转换为类型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;
}
我目前的解决方案只是抑制警告。 ...也许有更好的方法来遍历枚举。
您还可以使用下一个approach来修复警告:
foreach (TextureSet t in (TextureSet[]) Enum.GetValues(typeof(TextureSet)))
{
}