[英]instantiating generic classes in c#
在下面的代码段中,输出为:
厄尼·伯特·埃尔莫
为什么最后一个输出是Elmo? 不应该是厄尼吗? 因为我用new Cat();
实例化了dog.Creature
对象new Cat();
。 我认为, Name
的属性Cat
类覆盖Name
的属性Creature
类。
class Class1
{
public static void Main(string[] args)
{
var dog = new Dog();
var cat = new Cat();
dog.Creature = new Cat();
Console.WriteLine(cat.Name); //outputs Ernie
Console.WriteLine(dog.Name); //outputs Bert
Console.WriteLine(dog.Creature.Name); //outputs Elmo, why not Ernie?
Console.Read();
}
}
public class Animal<T> where T : Creature
{
public T Creature { get; set; }
private string _name = "Oscar";
public string Name { get { return _name; } set { _name = value; } }
}
public class Creature
{
private string _name = "Elmo";
public string Name { get { return _name; } set { _name = value; } }
}
public class Cat : Creature
{
private string _name = "Ernie";
public string Name { get { return _name; } set { _name = value; } }
}
public class Dog : Animal<Creature>
{
private string _name = "Bert";
public string Name { get { return _name; } set { _name = value; } }
}
首先,这与泛型无关。 如果您这样写,您将得到完全相同的行为:
Creature cat = new Cat();
Console.WriteLine(cat.Name);
不要忘记Dog.Creature
的编译时类型是Creature
。
我认为Cat类的Name属性会覆盖Creature类的Name属性。
不,因为它不是虚拟属性,并且您还没有使用override
。 您应该有一个编译时警告, 明确指出您正在隐藏该成员,而不是覆盖它:
Test.cs(30,19): warning CS0108: 'Cat.Name' hides inherited member
'Creature.Name'. Use the new keyword if hiding was intended.
如果将“ Cat
和Creature
更改为这样,它将起作用:
public class Creature
{
private string _name = "Elmo";
public virtual string Name { get { return _name; } set { _name = value; } }
}
public class Cat : Creature
{
private string _name = "Ernie";
public override string Name { get { return _name; } set { _name = value; } }
}
...但是我个人还是想避免这种情况。 为什么不只在Creature
使用二传手? 您为什么要在Cat
对象中有两个_name
字段? 并不是说它们旨在满足不同的目的,不是吗?
目前尚不清楚您要实现的目标,但几乎可以肯定的是,我会给Creature
类一个构造函数,以名称作为参数。 如果可能的话,我可能也将属性设置为只读。
我认为Cat类的Name属性会覆盖Creature类的Name属性
不,它隐藏了。 您有两个具有相同名称的不同属性。 如果要覆盖它,则需要将基本属性设为virtual
并在继承的类上使用override
关键字:
public class Creature
{
private string _name = "Elmo";
public virtual string Name { get { return _name; } set { _name = value; } }
}
public class Cat : Creature
{
private string _name = "Ernie";
public override string Name { get { return _name; } set { _name = value; } }
}
至于为什么看到“ Elmo”而不是“ Ernie”的原因-这是因为Dog
是Animal<Creature>
,所以属性Dog.Creature
的类型为Creature
。 即使您传递了Cat
,也由于没有覆盖 Name
属性,所以会调用Creature.Name
。 如果您覆盖了 Name
,那么将改为调用Cat.Name
。
一个好的做法是阅读IDE给您的警告。
warning CS0108: 'Program.Cat.Name' hides inherited member 'Program.Creature.Name'. Use the new keyword if hiding was intended.
warning CS0108: 'Program.Dog.Name' hides inherited member 'Program.Animal<Program.Creature>.Name'. Use the new keyword if hiding was intended.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.