在下面的代码中,输出是;
欧尼 伯特 毛毛
为什么最后一个输出是Elmo?不应该是厄尼吗?因为我使用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; } }
}
答案 0 :(得分:15)
首先,这与泛型无关。如果你写下来,你会得到完全相同的行为:
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
中使用setter?为什么您希望_name
对象中有两个Cat
字段?这不是说它们意味着服务于不同的目的,是吗?
目前还不清楚你要实现的是什么,但我几乎肯定会给Creature
类一个构造函数,并将该名称作为参数。如果可能的话,我可能会将该属性设为只读。
答案 1 :(得分:3)
我认为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; } }
}
关于为什么你正在看到&#34; Elmo&#34;而不是&#34;厄尼&#34; - 因为Dog
是Animal<Creature>
,所以属性Dog.Creature
的类型为Creature
。即使您传入Cat
,由于Name
属性未被重写,因此会调用Creature.Name
。如果您 overrode Name
,则会调用Cat.Name
。
答案 2 :(得分:3)
一个好的做法是阅读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.