Ключевое слово [default] не работает для C# generi c типа возвращаемого значения? - PullRequest
0 голосов
/ 06 марта 2020

Я конвертирую старый код C# для использования C# 8 и столкнулся с этой проблемой:

class MyList<T> : IMyEnumberable<T>
{
    public T GetDefault()
    {
        return default;// a default expression introduces a null value when 'T' is a non-nullable reference type
    }
}

Не удалось скомпилировать и говорит

выражение по умолчанию вводит нулевое значение, когда 'T' является необнуляемым ссылочным типом

Я не уверен, в чем здесь проблема - какие-либо объяснения?

Ответы [ 2 ]

2 голосов
/ 06 марта 2020

Проблема в том, что кто-то может сделать:

var list = new MyList<string>();
string d = list.GetDefault();

Так как они создали MyList<string>, то T равно string (то есть строка без значения NULL). Поэтому, поскольку GetDefault() возвращает T, это должно означать, что он возвращает ненулевую строку.

Однако, если они вызывают GetDefault(), это вернет default(string), то есть null. Они получат null, когда не ожидали его!


Вы не можете помешать кому-либо создать MyList<string>: нет синтаксиса, чтобы сказать "T must только может иметь тип NULL и не должен иметь тип NULL.

Если вы ограничите T значением struct или class, вы можете написать:

class MyList<T> : IMyEnumberable<T> where T : struct // or : class
{
    public T? GetDefault()
    {
        return default;
    }
}

В качестве альтернативы, вы можете добавить [MaybeNull] к типу возвращаемого значения GetDefault(), чтобы сказать, что, даже если он возвращает TT может не иметь значения NULL), этот метод может на самом деле return null.

(Обратите внимание, что в настоящее время это влияет только на абонентов из GetDefault(), а не на фактическое тело, поэтому вам все равно понадобится оператор подавления нулей ! Похоже, это скоро изменится):

using System.Diagnostics.CodeAnalysis;

class MyList<T> : IMyEnumberable<T>
{
    [return: MaybeNull]
    public T GetDefault()
    {
        return default!;
    }
}

SharpLab .

1 голос
/ 06 марта 2020

Вы не накладываете никаких ограничений на ваш шаблон c T, поэтому в основном T может быть чем угодно. Вот почему вы получили значение по умолчанию null.

var test = new MyList<SomeClass>().GetDefault(); // This gives you null
var test2 = new MyList<int>().GetDefault(); // This gives you 0

Если вы хотите, чтобы T был не обнуляемым, используйте это.

class MyList<T> where T : struct
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...