在下面的代码段中,输出是;
厄尼·伯特·埃尔莫
为什么最后的输出是Elmo?不是应该是厄尼吗?因为我用dog.Creature实例化new Cat();对象。我认为Name类的Cat属性覆盖了Creature类的Name属性。
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; } }
}发布于 2013-08-20 13:41:08
首先,这与泛型无关。如果你写的话,你会得到完全相同的行为:
Creature cat = new Cat();
Console.WriteLine(cat.Name);不要忘记,编译时类型的Dog.Creature是Creature。
我认为猫类的名称属性超过了生物类的名称属性。
不,因为它不是虚拟财产,而且您没有使用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类一个以名称作为参数的构造函数。如果有可能的话,我可能也会把这个财产改为只读的。
发布于 2013-08-20 13:42:14
我认为猫类的名称属性覆盖了生物类的名称属性。
不,它藏起来了。您有两个同名的不同属性。如果要重写它,则需要使基本属性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。
发布于 2013-08-20 13:43:02
一个好的做法是阅读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.https://stackoverflow.com/questions/18336503
复制相似问题