简体   繁体   中英

There is no implicit reference conversion

I have the following code which doesn't compile. I can't figure out why. Can someone please help?

var mercedes = new Mercedes().WithEngine(new LargeEngine());
var volkswagen = new Volkswagen().WithEngine(new SmallEngine());

public class Mercedes : Car<LargeEngine>
{
}

public class Volkswagen: Car<SmallEngine>
{
}

public class Engine
{
}

public class LargeEngine : Engine
{
}

public class SmallEngine : Engine
{
}

public class Car<T> where T : Engine
{
    internal T? Engine { get; set; }
}

public static class ExtensionMethods
{
    public static TCar WithEngine<TCar>(this TCar car, Engine engine)
        where TCar : Car<Engine>
    {
        car.Engine = engine;

        return car;
    }
}

The code above doesn't compile with the error:

The type 'Mercedes' cannot be used as type parameter 'TCar' in the generic type or method 'ExtensionMethods.WithConfiguration(TCar, Engine)'. There is no implicit reference conversion from 'Mercedes' to 'Car<Engine>'

What I understand is that 'Mercedes' type cannot be casted implicitly into 'Car<Engine>' type. But I also cannot figure out a way to cast it explicitly.

Thanks!

Modify the definition of the WithEngine extension method to take a generic type parameter that is constrained to the Car class, where T is a type parameter that is derived from the Engine class.

public static class ExtensionMethods
{
    public static TCar WithEngine<TCar, TEngine>(this TCar car, TEngine engine)
        where TCar : Car<TEngine>
        where TEngine : Engine
    {
        car.Engine = engine;

        return car;
    }
}

Why?

Car<LargeEngine> does not inherit from Car<Engine> , and cannot be implicitly converted to it.

Imagine if generic types did implement inheritance like this. Then we would be able to write the following code:

List<LargeEngine> largeEngines = new List<LargeEngine>();
List<Engine> allEngines = largeEngines;

// Uh-oh - this allows us to add a small engine to the list
allEngines.Add(new SmallEngine());

// The first item in the list is a SmallEngine, not a LargeEngine!
// What should this line do?
LargeEngine x = largeEngines[0];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM