简体   繁体   中英

Generics constraint doesn't appear to work in C#

error CS0029: Cannot implicitly convert type `Manager<T>' to `Manager<Asset>'

I don't understand why I'm getting the above compile-time error with the code below. Since the T type associated with Manager must derive from Asset, shouldn't it work?

public class Manager<T> where T : Asset
{
    public Manager()
    {
        var t = new Test();
        t.Manager = this; //compile-time error
    }
}

public class Test
{
    public Manager<Asset> Manager;
}

Since the T type associated with Manager must derive from Asset, shouldn't it work?

No, because the type parameter in generic classes is not covariant . That is, if you have DerivedAsset : Asset , then you are not allowed to assign Manager<Asset> manager = new Manager<DerivedAsset>() .

You can make a type parameter covariant by using out T , but this is only possible for interfaces. So you would need this:

public interface IManager<out T> where T : Asset { }

public class Test
{
    public IManager<Asset> Manager;
}

Now you should be able to write your original code, making Manager<T> implement IManager<T> :

public class Manager<T> : IManager<T> 
    where T : Asset
{
    public Manager()
    {
        var t = new Test();
        t.Manager = this;     // ok, because T in IManager<T> is covariant
    }
}

(As @sjkm noted, you could also simply do a cast: t.Manager = (Manager<Asset>)this; . But this would only work if you are sure that the T in Manager<T> is never a derived class -- if Asset were sealed, for example.)

Just because a T is an Asset doesn't mean that a Manager<T> is a Manager<Asset> . It would work if Manager<T> was covariant in T , but classes can't be covariant in C# (only interfaces and delegates can).

Instead, you can make Test generic as well:

public class Test<T> where T : Asset
{
    public Manager<T> Manager;
}

And it should now work as expected.

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