Col*_*dal 6 c# visual-studio c#-8.0 nullable-reference-types
我正在编写一个具有泛型类型的函数TVal。我写了这一行:
var zeroBased = new TVal[size];
然后在 Visual Studio (VS) 中,我使用 alt+enter 替换var为显式类型。这是我得到的:
TVal[]? zeroBased = new TVal[size];
我很惊讶地发现?运算符,表明该类型可能可以为空。我认为我会足够安全,假设类型在创建时永远不会为空new,并且可以刚刚完成:
TVal[] zeroBased = new TVal[size];
是否存在在 C# 中实例化新数组可以返回 null 的情况?
注意:代码似乎在没有 的情况下编译得很好?,我只是对 VS 的建议很感兴趣......
打开 Visual Studio,与下面指定的版本相同,创建一个新项目,根据下面的 VS 项目文件内容启用可为空类型,创建一个新类,并弹出此函数:
public void Test<T>(int size)
{
  var tArr = new T[size];
}
选择var并点击alt+enter,然后选择var用显式类型替换。如果行为与我所经历的相同,您将得到:
public void Test<T>(int size)
{
  T[]? tArr = new T[size];
}
我们在这个项目中使用 C# 8 并且我们启用了 Nullables:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <Nullable>enable</Nullable>
    <LangVersion>8.0</LangVersion>
    <WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
    <TargetFramework>netstandard2.0</TargetFramework>
    <OutputType>Library</OutputType>
    <Version>1.0.0.9</Version>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
    <PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
  </ItemGroup>
</Project>
Microsoft Visual Studio Community 2019 版本 16.6.1 VisualStudio.16.Release/16.6.1+30128.74 Microsoft .NET Framework 版本 4.7.03062
安装版本:社区
C# 工具 3.6.0-4.20251.5+910223b64f108fcf039012e0849befb46ace6e66 IDE 中使用的 C# 组件。根据您的项目类型和设置,可能会使用不同版本的编译器。
我想用我自己的解释来扩展现有的答案。MikeJ 的回答解决了这个问题并触及了它的核心。这一切都归结为启用了可空性 - 我们在这个项目中拥有它(但不是其他人,这让我失望!)。
Iliar Turdushev 的回答然后添加了一些明确的参考资料以支持原始答案。特别是,我们注意到 C# 团队最近在 Github 上的讨论。该文件以及现有的答案引用了以下内容:
在这一点上,我们已经看到大量代码需要人们拼出类型而不是使用 var,因为代码可能会在以后分配 null。
如果没有上下文,我发现这很难理解。所以这里是解释上述内容的上下文:
var current = myLinkedList.Head; // annotated not null
while (current is object)
{
    ...
    current = current.Next; // warning, Next is annotated nullable, but current is non-null
}
分解一下,让我们看看第一行:
var current = myLinkedList.Head; // annotated not null
由于该Head属性被注释为非空,编译器将 var 解释为不可为空是完全可以的。然而,这种不可空性将永远与变量保持一致,即使在程序中的某个时刻,我们想让它为空,例如在这一行中:
 current = current.Next; // warning, Next is annotated nullable, but current is non-null
C# 团队说,好吧,我们在这里有两个选择。我们可以var始终将其解释为可为空的,也可以将其解释为不可为空的,当它可以从上下文中推断出来时,并允许用户指定var?明确声明他们想要一个可为空的类型。但是我阅读他们的文件var?有点违反了整个原则var,即方便。如果我们每次使用它时都必须?在末尾添加一个额外的var东西,那么可能是我们明确类型并停止使用 var 的时候了。
因此,C# 团队得出结论:
使 var 具有可空的注释类型并正常推断流类型。
这意味着,如果您将不可空值分配给 a var,您可以稍后在代码中安全地将空值分配给相同的引用,而不会收到任何警告。汉斯也对此发表了评论。因此,例如,将其带回原来的 Q,我可以这样做:
public void Test<T>(int size)
{
  var tArr = new T[size];
  //Some code
  tArr = null; //This is OK, because var is treated as T[]?, not T[]
}
而且我不会收到任何警告。所以 VS 在这里表现得很好 - 它尊重编译器的行为,将 avar视为可空的,按照设计,即使该 var 被初始化为不可为空的 value。意思是,这对我来说是关键点,也是我问题的核心:
作为程序员,在将 var 转换为显式类型后删除可空性取决于您,如果这是您想要的。
这就是我在这种情况下要做的!
| 归档时间: | 
 | 
| 查看次数: | 352 次 | 
| 最近记录: |