Подтвердить что ты не робот

Невозможно неявно преобразовать производный тип в его базовый общий тип

У меня есть следующие классы и интерфейсы:

public interface IThing
{
    string Name { get; }
}

public class Thing : IThing
{
    public string Name { get; set; }
}

public abstract class ThingConsumer<T> where T : IThing
{
    public string Name { get; set; }
}

Теперь у меня есть factory, который вернет объекты, полученные из ThingConsumer, например:

public class MyThingConsumer : ThingConsumer<Thing>
{
}

Теперь мой factory выглядит следующим образом:

public static class ThingConsumerFactory<T> where T : IThing
{
    public static ThingConsumer<T> GetThingConsumer(){
        if (typeof(T) == typeof(Thing))
        {
            return new MyThingConsumer();
        }
        else
        {
            return null;
        }
    }
}

Я сработал с этой ошибкой: Error 1 Cannot implicitly convert type 'ConsoleApplication1.MyThingConsumer' to 'ConsoleApplication1.ThingConsumer<T>'

Кто-нибудь знает, как выполнить то, что я пытаюсь здесь?

Спасибо!

Крис

4b9b3361

Ответ 1

Если вы создаете ThingConsumer<T> интерфейс, а не абстрактный класс, тогда ваш код будет работать как есть.

public interface IThingConsumer<T> where T : IThing
{
    string Name { get; set; }
}

Изменить

Необходимо еще одно изменение. В ThingConsumerFactory верните тип возврата IThingConsumer<T>:

return (IThingConsumer<T>)new MyThingConsumer();

Ответ 2

Компилятор обходит конверсию с MyThingConsumer до ThingConsumer<T>, хотя T:IThing и MyThingConsumer:Thingconsumer<Thing> и Thing:IThing. Это довольно много обручей, чтобы проскочить!

Код работает, если вы используете return new MyThingConsumer() as ThingConsumer<T>; вместо прямого трансляции. Вы знаете, что результат никогда не будет null, и компилятор счастлив, потому что во время выполнения гарантируется возвращаемое значение правильного типа.

Edit: Вот полный код, который я использовал для тестирования (в Snippy):

public interface IThing
{
    string Name { get; }
}

public class Thing : IThing
{
    public string Name { get; set; }
}

public abstract class ThingConsumer<T> where T : IThing
{
    public string Name { get; set; }
}

public class MyThingConsumer : ThingConsumer<Thing>
{
}

public static class ThingConsumerFactory<T> where T : IThing
{
    public static ThingConsumer<T> GetThingConsumer()
    {
        if (typeof(T) == typeof(Thing))
        {
            return new MyThingConsumer() as ThingConsumer<T>;
        }
        else
        {
            return null;
        }
    }
}

...

var thing = ThingConsumerFactory<Thing>.GetThingConsumer();
Console.WriteLine(thing);

Ответ 3

Вам нужно определить свой класс, как я полагаю:

public class MyThingConsumer<Thing> : ThingConsumer

Причина в том, что ThingConsumer уже набрал в своем определении: where T : IThing

Теперь вы можете сделать вызов return new MyThingConsumer<T>();.

Это должно в свою очередь соответствовать ожидаемому типу возврата ThingConsumer<T>

ИЗМЕНИТЬ

Извините за путаницу, вот что должно работать:

public class MyThingConsumer<T> : ThingConsumer<T> where T : IThing

и

return new MyThingConsumer<T>();