在c#中实例化泛型类

时间:2013-08-20 13:37:29

标签: c# .net visual-studio-2010 class generics

在下面的代码中,输出是;

  

欧尼   伯特   毛毛

为什么最后一个输出是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; } }
}

3 个答案:

答案 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.

如果您将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中使用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; - 因为DogAnimal<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.