Cannot implicitly convert derived type to its base generic type

后端 未结 3 1806
北海茫月
北海茫月 2020-12-20 10:56

I have the following classes and interfaces:

public interface IThing
{
    string Name { get; }
}

public class Thing : IThing
{
    public string Name { get         


        
相关标签:
3条回答
  • 2020-12-20 11:28

    The compiler is stumbling over the conversion from MyThingConsumer to ThingConsumer<T> even though T:IThing and MyThingConsumer:Thingconsumer<Thing> and Thing:IThing. Which is quite a few hoops for it to jump through!

    The code works if you use return new MyThingConsumer() as ThingConsumer<T>; instead of a direct cast. You know the result will never be null, and the compiler is happy because it is guaranteed a return value of the right type at runtime.

    Edit: Here is the full code I used for testing (in 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);
    
    0 讨论(0)
  • 2020-12-20 11:44

    If you make ThingConsumer<T> an interface rather than an abstract class, then your code will work as is.

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

    Edit

    One more change needed. In ThingConsumerFactory, cast back to the return type IThingConsumer<T>:

    return (IThingConsumer<T>)new MyThingConsumer();
    
    0 讨论(0)
  • 2020-12-20 11:45

    You need to define your class like this I believe:

    public class MyThingConsumer<Thing> : ThingConsumer
    

    The reason is that ThingConsumer is already typed in its definition with this: where T : IThing

    Now, you can make the call return new MyThingConsumer<T>();.

    This should in turn match the expected return type of ThingConsumer<T>

    EDIT

    Sorry for the confusion, here is what should work:

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

    and

    return new MyThingConsumer<T>();
    
    0 讨论(0)
提交回复
热议问题