繁体   English   中英

在C#中实例化泛型类

[英]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.

如果将“ 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; } }
}

...但是我个人还是想避免这种情况。 为什么不只在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”的原因-这是因为DogAnimal<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.

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