C# 铸造通用MyClass<;儿童>;给我的班级<;家长>;在C中#

C# 铸造通用MyClass<;儿童>;给我的班级<;家长>;在C中#,c#,generics,casting,C#,Generics,Casting,假设我有一个父类Animal,其中包含子类Cat和Dog。我还有一个建筑,其中T可以是任何动物 public class<T> Building { public T Inhabitant {get; set;} } 公共类建筑 { 公共T居民{get;set;} } 现在,我想创建一些有猫的建筑物和一些有狗的建筑物(基于仅在运行时可用的参数)。为此,我尝试创建以下方法: private Building<Animal> populateBuilding(st

假设我有一个父类
Animal
,其中包含子类
Cat
Dog
。我还有一个
建筑
,其中T可以是任何
动物

public class<T> Building
{
    public T Inhabitant {get; set;}
}
公共类建筑
{
公共T居民{get;set;}
}
现在,我想创建一些有猫的建筑物和一些有狗的建筑物(基于仅在运行时可用的参数)。为此,我尝试创建以下方法:

private Building<Animal> populateBuilding(string animalKind)
{
    if(animalKind == "cat")
    {
        return new Building<Cat>;
    }
    if(animalKind == "dog")
    {
        return new Building<Dog>;
    }
    return null;
}
private Building populateBuilding(字符串animalKind)
{
if(animalKind==“cat”)
{
归还新建筑物;
}
如果(animalKind==“狗”)
{
归还新建筑物;
}
返回null;
}

但是,我不能这样做,因为编译器告诉我,
Building/Building
不能强制转换为
Building
。我发现了几个例子,其中描述了类似的问题,但使用了列表(例如,
List,List,List
)。然而,我并没有在我的案例中使用列表,我想知道它是否仍然是相同的情况

例如,你应该读一些关于协方差和逆变换的文章

在您的情况下,类
建筑
的设计不允许任何一种

假设允许它以协变方式使用
建筑
。然后它将允许以下代码段:

var dogHouse = new Building<Dog>();
var house = (Building<Animal>) dogHouse; // Casting to base class

house.Inhabitant = new Cat(); // Inhabitant of a Building<Animal> is any Animal
dogHouse.Inhabitant.Bark(); // Meow!
var dogHouse=新建筑();
var house=(建筑)dogHouse;//铸造到基类
house.resident=新猫();//建筑物的居住者是任何动物
狗屋。居民。树皮();//喵!
如果泛型的方法只返回类型为
T
的值(作为返回值或
out
-参数),则泛型可以与其类型参数
T
协同使用。如果泛型的方法只接受
T
类型的值作为参数,则泛型可以与其类型参数
T
协变使用。在您的例子中,有两种情况,即,
get\u resident
返回
Animal
set\u resident
接受
Animal

public class<T> Building
{
    public T Inhabitant {get; set;}
}

此外,正如在评论中正确指出的那样,在C#中,协方差和逆变的概念仅适用于接口和委托。

例如,您应该阅读一些关于协方差和逆变的文章

在您的情况下,类
建筑
的设计不允许任何一种

假设允许它以协变方式使用
建筑
。然后它将允许以下代码段:

var dogHouse = new Building<Dog>();
var house = (Building<Animal>) dogHouse; // Casting to base class

house.Inhabitant = new Cat(); // Inhabitant of a Building<Animal> is any Animal
dogHouse.Inhabitant.Bark(); // Meow!
var dogHouse=新建筑();
var house=(建筑)dogHouse;//铸造到基类
house.resident=新猫();//建筑物的居住者是任何动物
狗屋。居民。树皮();//喵!
如果泛型的方法只返回类型为
T
的值(作为返回值或
out
-参数),则泛型可以与其类型参数
T
协同使用。如果泛型的方法只接受
T
类型的值作为参数,则泛型可以与其类型参数
T
协变使用。在您的例子中,有两种情况,即,
get\u resident
返回
Animal
set\u resident
接受
Animal

public class<T> Building
{
    public T Inhabitant {get; set;}
}

此外,正如在评论中正确指出的那样,在C#中,协方差和逆变的概念仅适用于接口和委托。

您应该能够按照以下方式执行:

private Building<Animal> populateBuilding(string animalKind)
{
    var building = new Building<Animal>();

    if (animalKind == "cat")
    {
        return new Building<Animal>
        {
            Inhabitant = new Cat()
        };
    }
    if (animalKind == "dog")
    {
        return new Building<Animal>
        {
            Inhabitant = new Dog()
        };
    }

    return null;
}
private Building populateBuilding(字符串animalKind)
{
var building=新建筑();
if(animalKind==“cat”)
{
归还新楼
{
居民=新猫()
};
}
如果(animalKind==“狗”)
{
归还新楼
{
居民=新狗()
};
}
返回null;
}

您应该能够按如下方式进行操作:

private Building<Animal> populateBuilding(string animalKind)
{
    var building = new Building<Animal>();

    if (animalKind == "cat")
    {
        return new Building<Animal>
        {
            Inhabitant = new Cat()
        };
    }
    if (animalKind == "dog")
    {
        return new Building<Animal>
        {
            Inhabitant = new Dog()
        };
    }

    return null;
}
private Building populateBuilding(字符串animalKind)
{
var building=新建筑();
if(animalKind==“cat”)
{
归还新楼
{
居民=新猫()
};
}
如果(animalKind==“狗”)
{
归还新楼
{
居民=新狗()
};
}
返回null;
}

原因是协方差和反方差。更具体地说,想象一下,如果你可以这样做
Building b=new Building
,那么你就可以
b.resident=new Animal()
。正如您看到的,将
Animal()
对象指定给
Cat
引用类型属性是不允许的。问题是什么?你是在要求解释为什么会发生这种情况吗?或者,您是在寻求关于如何设计代码的建议吗?原因是协方差和反方差。更具体地说,想象一下,如果你可以这样做
Building b=new Building
,那么你就可以
b.resident=new Animal()
。正如您看到的,将
Animal()
对象指定给
Cat
引用类型属性是不允许的。问题是什么?你是在要求解释为什么会发生这种情况吗?或者您是在寻求如何设计代码的建议?虽然我不完全理解协方差和逆变(今天稍早阅读那篇文章),但您的示例很好地描述了这个问题。谢谢协方差和逆方差只对接口有效,对类无效。@YacoubMassad,是的,的确如此。还有委托(本质上是使用单个方法的接口的语法糖)。虽然我不完全理解协方差和逆变(今天稍早阅读那篇文章),但您的示例很好地描述了这个问题。谢谢协方差和逆方差只对接口有效,对类无效。@YacoubMassad,是的,的确如此。还有委托(本质上是使用单个方法的接口的语法糖)。