Nullable generi c ссылочный тип - PullRequest
1 голос
/ 03 апреля 2020

У меня есть следующая (работающая) служба, реализованная с использованием C # 8, но с отключенными ссылочными типами:

public class Foo { }

public interface IFooService
{
    Task<T> Get<T>() where T : Foo;
}

public FooService : IFooService
{
    async Task<T> IFooService.Get<T>() { /* returns either a valid Foo implementation or null */ }
}

Я пытался включить C # 8 для ссылочных типов, но не могу избавиться от ошибок или предупреждений, что бы я ни делал. Новый тип интерфейса:

public interface IFooService
{
    // T IS nullable AND a reference type.
    // There is no ambiguity as of 'T?' meaning here, because it can't be a struct.
    Task<T?> Get<T>() where T : Foo;
}

Когда я использую следующую реализацию:

public class FooService : IFooService
{
    async Task<T?> IFooService.Get<T>() { /* ... */ }
}

Я получаю ошибку:

'FooService' does not implement interface member 'IFooService.Get<T>()'

Что я не делаю понять, потому что подписи в интерфейсе и в реализации в точности совпадают.

Однако, когда я реализую интерфейс как этот (который генерирует подпись, автоматически генерируемая Visual Studio):

public class FooService : IFooService
{
    async Task<T> IFooService.Get<T>() { /* ... */ }
}

Я получаю следующее предупреждение:

Nullability of reference types in return type doesn't match implemented member 'Task<T?> IFooService.Get<T>()'.

1 Ответ

2 голосов
/ 03 апреля 2020

Вам необходимо добавить общее ограничение c в вашу реализацию:

public class FooService : IFooService
{
    async Task<T?> IFooService.Get<T>() where T : class
    {
        /* ... */ 
    }
}

Интересно, как Visual Studio не добавляет T? к реализации, которую она генерирует. Я подозреваю, что это ошибка в редакторе.

Вы упоминаете, что ваш константный тип на самом деле против Foo. Это означает, что ваш код будет выглядеть так:

public class Foo
{
}

public interface IFooService
{
    // T IS nullable AND a reference type.
    // There is no ambiguity as of 'T?' meaning here, because it can't be a struct.
    Task<T?> Get<T>() where T : Foo;
}

public class FooService : IFooService
{
    async Task<T?> IFooService.Get<T>() where T : class
    {
        throw new NotImplementedException();
    }
}

Ограничение типа на интерфейсе, но в реализации вы не можете указать фактическое имя типа, но вы можете указать, что это должен быть класс .

...