C # 8, что означает "по умолчанию!"делать на универсальных типах? - PullRequest
2 голосов
/ 05 апреля 2019

Просто поигрался с бета-версией C # 8.0 и обновил часть моего кода, чтобы использовать обнуляемые ссылочные типы.

У меня есть класс стилей узла для реализации 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;
    }
}

, если последняя строка ctor равнаизменилось на

   this.value = default!;

, как я видел здесь в другом вопросе, тогда он компилируется просто отлично.Но я не понимаю, что здесь делает !, и гуглить это довольно сложно, так как в большинстве случаев гугл игнорирует пунктуацию.

Что делает default!?

Ответы [ 2 ]

4 голосов
/ 05 апреля 2019

Обнуляемые ссылочные типы используют статический анализ потока, чтобы выяснить, имеется ли у вас возможное нулевое значение (таким образом, при выдаче предупреждения переменной присваивается нулевое значение).

The! используется, чтобы позволить разработчику подавить сгенерированное предупреждение. По существу переопределяет компилятор.

1 голос
/ 05 апреля 2019

Это ничего не делает.Если вы посмотрите на IL, сгенерированный для каждого метода, он одинаков.«Обнуляемые ссылочные типы» - это предупреждение / ошибка времени компиляции, гарантирующее, что разработчики явно помечают переменные как потенциально присвоенные нулевым значениям.Если переменной было присвоено значение с помощью!флаг, то компилятор не будет предупреждать всякий раз, когда на переменную ссылаются без проверки на нулевое значение.

Поскольку T не имеет ограничений, он выдаст предупреждение Warning Предупреждение будетудаляется при замене default на 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;
        }
    }
}

IL

      IL_0008: ldarg.0      // this
      IL_0009: ldflda       !0/*T*/ class TestingGround.Program/GenericClass`1<!0/*T*/>::Value
      IL_000e: initobj      !0/*T*/
...