Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.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#_Generics_Interface_Instantiation - Fatal编程技术网

C#使用使用接口的泛型进行转换

C#使用使用接口的泛型进行转换,c#,generics,interface,instantiation,C#,Generics,Interface,Instantiation,我有一些实现这些接口的通用接口和类,如下所示: interface A<M, N> where M : X<N> where N : Y { } class B<M, N> : A<M, N> where M : X<N> where N : Y { } interface X<M> where M :

我有一些实现这些接口的通用接口和类,如下所示:

    interface A<M, N>
        where M : X<N>
        where N : Y
    {
    }
    class B<M, N> : A<M, N>
        where M : X<N>
        where N : Y
    {

    }

    interface X<M> where M : Y
    {

    }
    interface Y
    {

    }
    class X1<M> : X<M> where M : Y
    {

    }
    class Y1 : Y
    {

    }
接口A
其中M:X
N:Y在哪里
{
}
B类:A
其中M:X
N:Y在哪里
{
}
接口X,其中M:Y
{
}
界面Y
{
}
类别X1:X,其中M:Y
{
}
Y1类:Y类
{
}
我知道这似乎是一种非常混乱的做事方式,但我在申请时需要它。我的问题是为什么我不能这样做:


A变量=新B()

差异需要明确(需要C#4.0);例如,这使其编译为协变(注意接口中的
out
修饰符):

接口A
其中M:X
N:Y在哪里
{
}
接口X,其中M:Y
{
}

但是,请注意,这也将您的界面限制为。。。协方差!例如,您不能有一个
Add(M)
方法,因为这需要是contavariant(aka
in
)。

Marc是正确的;只是想给你一些背景知识,解释为什么这不起作用。考虑以下代码的重新命名:

    interface IZoo<TCage, TAnimal>
        where TCage : ICage<TAnimal>
        where TAnimal : IAnimal
    {
    }

    class Zoo<TCage, TAnimal> : IZoo<TCage, TAnimal>
        where TCage : ICage<TAnimal>
        where TAnimal : IAnimal
    {
    }

    interface ICage<TAnimal> where TAnimal : IAnimal
    {
    }

    interface IAnimal
    {
    }

    class FishTank<TAnimal> : ICage<TAnimal> where TAnimal : IAnimal
    {
    }

    class Fish : IAnimal
    {
    }
你把长颈鹿围场放进水族馆!在一个您想要的转换是合法的并且IZoo可以有您选择的任何方法的世界中,我们无法维护类型安全

现在,这是唯一危险的,因为IZoo有这样一种方法。如果它没有这样的方法,那么你是对的,这可能是完全安全的。在C#4.0中,我们在语言中添加了一个功能,这样您就可以询问编译器“检查此接口是否可以安全地变为变量”,方法是用“out”注释要协变的类型参数,用“In”注释要逆变的类型参数。如果您这样做,那么编译器将为您检查您想要的差异是否可以被设置为类型安全的。如果不能,则不允许该类型的声明

StackOverflow上通常会出现这样的问题,人们会问为什么这是非法的:

List<Giraffe> giraffes = new List<Giraffe>();
List<Mammal> mammals = giraffes; // illegal

你刚刚在长颈鹿名单上加了一只老虎。同样的道理,只是一个简单得多的例子。

嘿,当我尝试这样做时,它说它的C#4.0语言功能出现错误,我该怎么办?@Twinhelix-你使用的是什么版本的Visual Studio,目标是什么平台版本?它在VS2010 Targeting.NET2.0上对我有效。在C#4.0之前。。。在非常有限的情况下,差异有点小。嘿,我正在运行VS2008和.NET3.5。我真的不能改变我的环境设置,有没有办法解决这个问题?我不能升级,因为这是公司的电脑,有很多特权和其他。我希望有一个解决办法:P
Zoo<FishTank<Fish>, Fish> aquarium = new Zoo<FishTank<Fish>, Fish>();
IZoo<ICage<IAnimal>, IAnimal> zoo = aquarium;
    interface IZoo<TCage, TAnimal>
        where TCage : ICage<TAnimal>
        where TAnimal : IAnimal
    {
        void PutAnimalInCage(TCage cage, TAnimal animal);
    }
zoo.PutAnimalInCage(giraffePaddock, giraffe);
List<Giraffe> giraffes = new List<Giraffe>();
List<Mammal> mammals = giraffes; // illegal
mammals.Add(new Tiger());