Соответствие обнуляемости параметров универсального типа аргумента и возвращаемого типа - PullRequest
3 голосов
/ 09 октября 2019
public readonly struct Foo<T>
{
    // ...
    public T Value { get; }
}

public static Foo<string?> Bar(Foo<string?> foo)
{
    if (foo.Value is null) { /* Something */ }
    else { /* Some other thing */ }
    return foo;
}

public static void Main()
{
    var foo1 = new Foo<string>("s");
    var ret1 = Bar(foo1); // Warns because foo1's type parameter is not nullable

    var foo2 = new Foo<string?>("s");
    var ret2 = Bar(foo2); // Ok because foo2's type parameter is nullable
}
  • Могу ли я написать Bar, чтобы принять как Foo<string?>, так и Foo<string>?
  • Могу ли я аннотировать Bar, чтобы указать, "что входит, уходит", поэтому обнуляемость T возвращаемого Foo<T> будет таким же, как обнуляемость T параметра Foo<T>?

1 Ответ

0 голосов
/ 10 октября 2019

Строки в методе Foo<string?> Bar(Foo<string?> foo) не связаны, они имеют разные типы, и в настоящее время нет атрибута / способа аннотировать их предполагаемое отношение для компилятора. Однако параметр типа в универсальном методе Foo<T> Bar<T>(Foo<T> foo) будет одним типом с разделяемой обнуляемостью. Это будет работать, если сам тип не очень важен для нашего метода, но как написать метод, который принимает определенный тип для значения foo?

Добавление ограничения общего типа, такого как where T : MyType?, может помочь нам обойти эту проблемуЭта проблема. Обнуляемость разделяется и , на самом деле мы можем использовать определенный тип для работы. Проблема в том, что мы не можем написать where T : string?, потому что C # не позволяет использовать закрытые классы в качестве ограничений типов.

Это разумно, так как раньше это не имело бы смысла - зачем нам проектироватьметод как универсальный, если есть только один тип, который мы можем использовать? Ну, с C # 8 и обнуляемыми ссылочными типами в дикой природе, я думаю, у нас сейчас может быть веская причина. Может быть, команда может снять это ограничение, как оно сняло его для перечислений.

Чтобы ответить на вопрос:

  • Нет атрибута для аннотирования моего варианта использования в вопросе.
  • Обобщения могут использоваться с ограничениями типов, но только с типами, которые не являются запечатанными.

Примечание: даже если C # не позволяет нам использовать запечатанные типы в качестве ограничений типов, IL делает,Поэтому, если ткачество является опцией, мы можем добавить ограничения запечатанного типа к параметрам универсального типа. Решение, подобное ExtraConstraints , может быть расширено для обеспечения этой функциональности.

...