C#8 什么是“默认!” 对泛型类型做什么?

cra*_*aig 6 c# generics non-nullable c#-8.0 nullable-reference-types

只是尝试使用 C# 8.0 Beta 并更新一些代码以使用可为 null 的引用类型。

我有一个用于 Trie 实现的节点样式类。每个节点都有一个类型为 的值T。根节点的构造函数不需要值,因此我将其设置为default。

这是一个简短的版本:

public class Trie<T>
{
    public readonly bool caseSensitive;
    public readonly char? letter;
    public readonly Dictionary<char, Trie<T>> children;
    public readonly Trie<T>? parent;
    public readonly int depth;
    public bool completesString;
    public T value;

    public Trie(bool caseSensitive = false)
    {
        this.letter = null;
        this.depth = 0;
        this.parent = null;
        this.children = new Dictionary<char, Trie<T>>();
        this.completesString = false;
        this.caseSensitive = caseSensitive;
        this.value = default;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果 ctor 的最后一行更改为

   this.value = default!;
Run Code Online (Sandbox Code Playgroud)

正如我在另一个问题中看到的那样,它编译得很好。但我不明白!这里在做什么,而且很难用谷歌搜索,因为谷歌似乎在大多数情况下忽略标点符号。

有什么default!作用?

Ada*_*arr 7

可空引用类型使用静态流分析来确定是否有可能的空值(从而发出警告,变量正在被分配空值)。

这 !用于允许开发人员抑制生成的警告。本质上是重写编译器。

  • 我还听说过它被称为“该死的操作员”(如:“该死的,它不是空的!”)(归属:Mads Torgersen)这个术语可能没有被法律“接受”...... (2认同)

use*_*730 3

它没有任何作用。如果您查看为每个方法生成的 IL,它是相同的。“可为空引用类型”是一个编译时警告/错误,以确保开发人员已将变量明确标记为可能被分配空值。如果变量已用 ! 赋值 如果没有检查空值,编译器将不会在任何时候取消引用变量时发出警告。

由于T没有限制,它会发出警告 警告

default如果您替换为which,则警告将被删除,default!这相当于说null!引用类型是弄巧成拙的;因为值类型default永远不会为空,所以这是双重的弄巧成拙。

此外,如果您使用GenericClass<T> where T : struct,default将不会发出警告。

using System;
using System.Collections.Generic;

namespace TestingGround
{
    public class Program
    {
        public class GenericClass<T>
        {
            public T Value;


            public GenericClass()
            {
                Value = default;
            }
        }

        static void Main(string[] args)
        {
            var gc = new GenericClass<string>();
            var strLength = gc.Value.Length;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

伊尔

      IL_0008: ldarg.0      // this
      IL_0009: ldflda       !0/*T*/ class TestingGround.Program/GenericClass`1<!0/*T*/>::Value
      IL_000e: initobj      !0/*T*/
Run Code Online (Sandbox Code Playgroud)