[英]Generics constraint doesn't appear to work in C#
error CS0029: Cannot implicitly convert type `Manager<T>' to `Manager<Asset>'
我不明白为什么我在下面的代码中遇到上述编译时错误。 由于与Manager关联的T类型必须从Asset派生,所以它行不通吗?
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;
}
由于与Manager关联的T类型必须从Asset派生,所以它行不通吗?
不可以,因为通用类中的类型参数不是协变的 。 也就是说,如果您具有DerivedAsset : Asset
,则不允许您分配Manager<Asset> manager = new Manager<DerivedAsset>()
。
您可以使用out T
使类型参数协变,但这仅适用于接口。 因此,您将需要以下内容:
public interface IManager<out T> where T : Asset { }
public class Test
{
public IManager<Asset> Manager;
}
现在您应该能够编写原始代码,使Manager<T>
实现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
}
}
(如@sjkm指出,你也可以简单地做一个投: t.Manager = (Manager<Asset>)this;
但如果你是确保这只会工作T
的Manager<T>
从来都不是一个派生类- -例如,如果Asset
被密封。)
仅仅因为T
是Asset
并不意味着Manager<T>
是Manager<Asset>
。 如果Manager<T>
在T
是协变的,但在C#中类不能是协变的(仅接口和委托可以),这将起作用。
相反,您也可以使Test
通用:
public class Test<T> where T : Asset
{
public Manager<T> Manager;
}
现在它应该可以按预期工作了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.