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

C# 泛型和类继承混淆

C# 泛型和类继承混淆,c#,generics,inheritance,covariance,C#,Generics,Inheritance,Covariance,下面的代码块是我遇到的一个问题的简化示例。但我得到一个错误,声称我无法将一种类型转换为另一种类型。我用LINQPad来测试它 void Main() { LivingThing<Appendage> mysteryAnimal = new Cat(); } public class Appendage { } public class Paw : Appendage { } public class LivingThing<TExtremity> where

下面的代码块是我遇到的一个问题的简化示例。但我得到一个错误,声称我无法将一种类型转换为另一种类型。我用LINQPad来测试它

void Main()
{
    LivingThing<Appendage> mysteryAnimal = new Cat();
}

public class Appendage { }
public class Paw : Appendage { }

public class LivingThing<TExtremity> where TExtremity : Appendage { }
public class Animal<TExtremity> : LivingThing<TExtremity> where TExtremity : Appendage { }
public class Cat : Animal<Paw> { }
void Main()
{
LivingThing mysteryAnimal=新猫();
}
公共类附件{}
公共类Paw:附件{}
公共类LivingThing,其中TExtremity:Appendage{}
公共类动物:生活在文本区Y:附属物{}
公共类猫:动物{}

当我知道Cat的定义使用了
LivingThing
Appendage
的子类时,为什么我不能将
Cat
转换为
LivingThing

通过向一个类添加一个方法,可以更容易地理解为什么您试图做的事情在没有一些修改的情况下无法工作:

public class LivingThing<TExtremity> where TExtremity : Appendage {
    private TExtremity extremity;
    public void SetExtremity(TExtremity e) {
        extremity = e;
    }
}

有一个问题:无论是
ILivingThing
还是
IAnimal
都不允许具有类型为
textreemy
的可设置属性,或者使用
textreemy
作为参数的方法;将具有更派生泛型参数的泛型类的实例分配给具有较少派生泛型参数的类的变量

在C#中,类不支持这一点。对于接口,必须显式指定它。将汇编以下文件:

void Main()
    {
        ILivingThing<Appendage> mysteryAnimal = new Cat();
    }

    public class Appendage { }
    public class Paw : Appendage { }

    public interface ILivingThing<out TExtremity> where TExtremity : Appendage { }
    public class Animal<TExtremity> : ILivingThing<TExtremity> where TExtremity : Appendage { }
    public class Cat : Animal<Paw> { }
void Main()
{
ILivingThing mysteryAnimal=新猫();
}
公共类附件{}
公共类Paw:附件{}
公共接口ILivingThing,其中textReviety:Appendage{}
公共类动物:ILivingThing where TExtremity:Appendage{}
公共类猫:动物{}

这对于您的实际代码是否可以接受取决于LivingThing是如何定义的;如果它是一个“标记类”(没有成员;存在只是为了作为派生点,将其子类标识为LivingThings),或者是一个没有非抽象成员的抽象类,那么它应该像一个符咒一样工作。如果该类中有成员代码,则需要从该类中提取协变接口。

因为
LivingThing
不是
LivingThing
-阅读协变…类是不变的-可以创建
ILivingThing
接口,然后可以执行
ILivingThing mysteryAnimal=new Cat()LivingThing mysteryAnimal=新动物()//作品
LivingThing mysteryAnimal=new LivingThing()//不
声称的复制品显然是相关的,但它没有回答OP的问题,即为什么不改变事情就不可能做他想做的事。投票重新开放。非常有趣。。。我把你的例子放进LINQPad来尝试一下,它在一些问题上出了问题。IAnimal界面上的
ILivingThing
显然不需要
out
?而
Cat
需要从接口继承(不是我以前拥有的类)。我熟悉方法的参数
out
,但不将其用于泛型。有什么好问题吗?或者有一篇文章介绍了它们吗?@NickAlbrecht,C#compiler的设计师之一,有一系列关于协方差的文章。在中,他讨论了在添加到语言中之前在模板参数中使用
In
out
的语法选项(请参见选项5)。太棒了,非常感谢您指出了正确的方向。感谢您抽出时间来帮助我:-)如果我两者都做了,在基类(非抽象)中有成员代码,但使用接口作为泛型where约束的限制,会怎么样?好的。太棒了,我必须研究一下如何传递这些实例,确定什么时候我真的需要一个强类型类或仅仅是一个接口,看看我是否能把它们都整理好。非常感谢:-)
void Main()
{
    ILivingThing<Appendage> mysteryAnimal = new Cat();
}

public class Appendage { }
public class Paw : Appendage { }

public interface ILivingThing<out TExtremity> where TExtremity : Appendage { }
// You have a choice of keeping Animal a class. If you do, the assignment
// Animal<Appendage> mysteryAnimal = new Cat()
// would be prohibited.
public interface IAnimal<TExtremity> : ILivingThing<out TExtremity> where TExtremity : Appendage { }
public class Cat : Animal<Paw> { }
void Main()
    {
        ILivingThing<Appendage> mysteryAnimal = new Cat();
    }

    public class Appendage { }
    public class Paw : Appendage { }

    public interface ILivingThing<out TExtremity> where TExtremity : Appendage { }
    public class Animal<TExtremity> : ILivingThing<TExtremity> where TExtremity : Appendage { }
    public class Cat : Animal<Paw> { }