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.