[英]instantiating generic classes in c#
In the piece of code below, the output is; 在下面的代码段中,输出为:
Ernie Bert Elmo 厄尼·伯特·埃尔莫
Why is the last output is Elmo? 为什么最后一个输出是Elmo? Shouldn't it be Ernie? 不应该是厄尼吗? Because i instantiate dog.Creature
object with new Cat();
因为我用new Cat();
实例化了dog.Creature
对象new Cat();
. 。 i thought that the Name
property of Cat
class overrides the Name
property of Creature
class. 我认为, 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; } }
}
Firstly, this has nothing to do with generics. 首先,这与泛型无关。 You'll get exactly the same behaviour if you write: 如果您这样写,您将得到完全相同的行为:
Creature cat = new Cat();
Console.WriteLine(cat.Name);
Don't forget that the compile-time type of Dog.Creature
is Creature
. 不要忘记Dog.Creature
的编译时类型是Creature
。
i thought that the Name property of Cat class overrides the Name property of Creature class. 我认为Cat类的Name属性会覆盖Creature类的Name属性。
No, because it's not a virtual property and you haven't used override
. 不,因为它不是虚拟属性,并且您还没有使用override
。 You should have a compile-time warning explicitly saying that you're hiding the member, not overriding it: 您应该有一个编译时警告, 明确指出您正在隐藏该成员,而不是覆盖它:
Test.cs(30,19): warning CS0108: 'Cat.Name' hides inherited member
'Creature.Name'. Use the new keyword if hiding was intended.
If you change Cat
and Creature
to be like this, it will work: 如果将“ 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; } }
}
... but personally I'd try to avoid this anyway. ...但是我个人还是想避免这种情况。 Why not just use the setter in Creature
? 为什么不只在Creature
使用二传手? Why would you want there to be two _name
fields in a Cat
object? 您为什么要在Cat
对象中有两个_name
字段? It's not like they're meant to serve different purposes, is it? 并不是说它们旨在满足不同的目的,不是吗?
It's not clear what you're trying to achieve, but I'd almost certainly give the Creature
class a constructor taking the name as a parameter. 目前尚不清楚您要实现的目标,但几乎可以肯定的是,我会给Creature
类一个构造函数,以名称作为参数。 I'd probably make the property read-only if at all possible, too. 如果可能的话,我可能也将属性设置为只读。
I thought that the Name property of Cat class overrides the Name property of Creature class 我认为Cat类的Name属性会覆盖Creature类的Name属性
No, it hides it. 不,它隐藏了。 You have two different properties with the same name. 您有两个具有相同名称的不同属性。 If you want to override it, you need to make the base property virtual
and use the override
keyword on the inherited class: 如果要覆盖它,则需要将基本属性设为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; } }
}
As to why you are seeing "Elmo" instead of "Ernie" - it's because Dog
is an Animal<Creature>
, so the property Dog.Creature
is of type Creature
. 至于为什么看到“ Elmo”而不是“ Ernie”的原因-这是因为Dog
是Animal<Creature>
,所以属性Dog.Creature
的类型为Creature
。 Even though you pass in a Cat
, since the Name
property is not overridden , Creature.Name
is called. 即使您传递了Cat
,也由于没有覆盖 Name
属性,所以会调用Creature.Name
。 If you had overrode Name
, then Cat.Name
would be called instead. 如果您覆盖了 Name
,那么将改为调用Cat.Name
。
A good practice is to read the warnings the IDE gives you. 一个好的做法是阅读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.