Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么使用泛型类型强制转换不起作用?_C#_.net_Generics_Types_Core - Fatal编程技术网

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();
    }
}