简体   繁体   English

在C#中实例化泛型类

[英]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: 如果将“ CatCreature更改为这样,它将起作用:

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”的原因-这是因为DogAnimal<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM