C# 为什么使用泛型类型强制转换不起作用?
何乐而不为, 所以我只想使用通用和铸造。但由于某种原因,它不起作用,我不知道为什么C# 为什么使用泛型类型强制转换不起作用?,c#,.net,generics,types,core,C#,.net,Generics,Types,Core,何乐而不为, 所以我只想使用通用和铸造。但由于某种原因,它不起作用,我不知道为什么 abstract class BaseModel {} class NewModel : BaseModel {} class BaseRepo<T> where T : BaseModel {} class NewRepo : BaseRepo<NewModel> {} class Test { public void Te
abstract class BaseModel {}
class NewModel : BaseModel {}
class BaseRepo<T> where T : BaseModel {}
class NewRepo : BaseRepo<NewModel> {}
class Test
{
public void TestMethod()
{
BaseRepo<BaseModel> t1 = new BaseRepo<BaseModel>();
BaseRepo<NewModel> t2 = new NewRepo();
BaseRepo<BaseModel> t3 = new BaseRepo<NewModel>();
// Cannot convert initializer type 'TestGeneric.BaseRepo<TestGeneric.NewModel> to target type 'TestGeneric.BaseRepo<BaseModel>'.
// Cannot implicitly convert type 'TestGeneric.BaseRepo<TestGeneric.NewModel>' to 'TestGeneric.BaseRepo<TestGeneric.BaseModel>'.
// Type 'NewModel' doesn't match expected type 'BaseModel'.
// Cannot convert source type 'TestGeneric.BaseRepo<TestGeneric.NewModel>' to target type 'TestGeneric.BaseRepo<TestGeneric.BaseModel>'.
BaseRepo<BaseModel> t4 = new NewRepo();
// Cannot convert initializer type 'TestGeneric.BaseRepo<TestGeneric.NewModel> to target type 'TestGeneric.BaseRepo<BaseModel>'.
// Cannot implicitly convert type 'TestGeneric.NewRepo' to 'TestGeneric.BaseRepo<TestGeneric.BaseModel>'.
// Cannot convert source type 'TestGeneric.NewRepo' to target type 'TestGeneric.BaseRepo<TestGeneric.BaseModel>'.
}
}
抽象类基模型{}
类NewModel:BaseModel{}
类BaseRepo,其中T:BaseModel{}
类NewRepo:BaseRepo{}
课堂测试
{
公共void TestMethod()
{
BaseRepo t1=新的BaseRepo();
BaseRepo t2=新的NewRepo();
BaseRepo t3=新的BaseRepo();
//无法将初始值设定项类型“TestGeneric.BaseRepo”转换为目标类型“TestGeneric.BaseRepo”。
//无法将类型“TestGeneric.BaseRepo”隐式转换为“TestGeneric.BaseRepo”。
//类型“NewModel”与预期的类型“BaseModel”不匹配。
//无法将源类型“TestGeneric.BaseRepo”转换为目标类型“TestGeneric.BaseRepo”。
BaseRepo t4=新的NewRepo();
//无法将初始值设定项类型“TestGeneric.BaseRepo”转换为目标类型“TestGeneric.BaseRepo”。
//无法将类型“TestGeneric.NewRepo”隐式转换为“TestGeneric.BaseRepo”。
//无法将源类型“TestGeneric.NewRepo”转换为目标类型“TestGeneric.BaseRepo”。
}
}
我只是不明白为什么t3和t4在t1和t2工作的同时抛出异常。即使是NewModel也是BaseModel的一个子类,最后两个也不起作用。这是由于泛型的协方差特性: 根据有关此tpoic的Microsoft文档: 协方差和逆方差是指能够 使用派生程度较高的类型(更具体)或派生程度较低的类型(较少) (特定的)比最初指定的。泛型类型参数支持 协方差和逆变,以提供更大的灵活性 分配和使用泛型类型。当你指的是一种类型 系统、协方差、逆变换和不变性具有以下特性 定义。这些示例假定一个名为base的基类和一个派生类 名为派生的类 协方差 使您能够使用比最初指定的派生类型更多的派生类型 您可以指定IEnumerable(IEnumerable(of)的实例 派生)到IEnumerable类型的变量 逆变 使您能够使用比最初更通用(派生更少)的类型 指定的 您可以在Visual Studio中指定动作(基本动作)的实例 基本)到类型为Action的变量 不变性 表示只能使用最初指定的类型;那么 不变泛型类型参数既不是协变的,也不是协变的 逆变的 无法在Visual Studio中指定List(List(of Base))的实例 基本)转换为列表类型的变量,反之亦然 协变类型参数使您可以使指定看起来 与普通多态性非常相似,如下代码所示 然后更改您的
BaseRepo
,如下所示:
public class BaseRepo<T> : ICovariant<T> where T : BaseModel { }
公共类BaseRepo:ICovariant其中T:BaseModel{}
现在,您可以执行以下操作:
BaseRepo<BaseModel> t1 = new BaseRepo<BaseModel>();
BaseRepo<NewModel> t2 = new NewRepo();
ICovariant<BaseModel> t3 = new BaseRepo<NewModel>();
ICovariant<BaseModel> t4 = new NewRepo();
BaseRepo t1=新的BaseRepo();
BaseRepo t2=新的NewRepo();
Iconvariant t3=新的BaseRepo();
Iconvariant t4=新的NewRepo();
孔代号如下:
public interface ICovariant<out T> where T : BaseModel
{
}
public abstract class BaseModel { }
public class NewModel : BaseModel { }
public class BaseRepo<T> : ICovariant<T> where T : BaseModel { }
class NewRepo : BaseRepo<NewModel> { }
class Test
{
public void TestMethod()
{
BaseRepo<BaseModel> t1 = new BaseRepo<BaseModel>();
BaseRepo<NewModel> t2 = new NewRepo();
ICovariant<BaseModel> t3 = new BaseRepo<NewModel>();
ICovariant<BaseModel> t4 = new NewRepo();
}
}
公共接口,其中T:BaseModel
{
}
公共抽象类基类{}
公共类NewModel:BaseModel{}
公共类BaseRepo:ICovariant,其中T:BaseModel{}
类NewRepo:BaseRepo{}
课堂测试
{
公共void TestMethod()
{
BaseRepo t1=新的BaseRepo();
BaseRepo t2=新的NewRepo();
Iconvariant t3=新的BaseRepo();
Iconvariant t4=新的NewRepo();
}
}
是的,我知道。VS向我展示了这个选项。但这是可行的:
BaseModel base=newnewmodel()
所以我不明白如果我把它作为泛型使用,为什么它不起作用。这是我真正的问题。@Davidzilagyi,我已经更新了我的答案,希望这能帮到你。@Davidzilagyi,这能帮到你吗?还有问题吗?如果答案对你有帮助,请接受解决方案,这样其他人也能从中受益。是的。这就像协方差的解释一样有帮助。谢谢:)这是我的荣幸:)检查副本-尤其是我的。我认为这很容易理解。
BaseRepo<BaseModel> t1 = new BaseRepo<BaseModel>();
BaseRepo<NewModel> t2 = new NewRepo();
ICovariant<BaseModel> t3 = new BaseRepo<NewModel>();
ICovariant<BaseModel> t4 = new NewRepo();
public interface ICovariant<out T> where T : BaseModel
{
}
public abstract class BaseModel { }
public class NewModel : BaseModel { }
public class BaseRepo<T> : ICovariant<T> where T : BaseModel { }
class NewRepo : BaseRepo<NewModel> { }
class Test
{
public void TestMethod()
{
BaseRepo<BaseModel> t1 = new BaseRepo<BaseModel>();
BaseRepo<NewModel> t2 = new NewRepo();
ICovariant<BaseModel> t3 = new BaseRepo<NewModel>();
ICovariant<BaseModel> t4 = new NewRepo();
}
}