首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在c#中实例化泛型类

在c#中实例化泛型类
EN

Stack Overflow用户
提问于 2013-08-20 13:37:28
回答 3查看 276关注 0票数 0

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

厄尼·伯特·埃尔莫

为什么最后的输出是Elmo?不是应该是厄尼吗?因为我用dog.Creature实例化new Cat();对象。我认为Name类的Cat属性覆盖了Creature类的Name属性。

代码语言:javascript
复制
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; } }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-20 13:41:08

首先,这与泛型无关。如果你写的话,你会得到完全相同的行为:

代码语言:javascript
复制
Creature cat = new Cat();
Console.WriteLine(cat.Name);

不要忘记,编译时类型的Dog.CreatureCreature

我认为猫类的名称属性超过了生物类的名称属性。

不,因为它不是虚拟财产,而且您没有使用override。您应该有一个编译时警告,显式地说您正在隐藏该成员,而不是覆盖它:

代码语言:javascript
复制
Test.cs(30,19): warning CS0108: 'Cat.Name' hides inherited member
        'Creature.Name'. Use the new keyword if hiding was intended.

如果您将CatCreature更改为这样,它将工作:

代码语言:javascript
复制
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类一个以名称作为参数的构造函数。如果有可能的话,我可能也会把这个财产改为只读的。

票数 15
EN

Stack Overflow用户

发布于 2013-08-20 13:42:14

我认为猫类的名称属性覆盖了生物类的名称属性。

不,它藏起来了。您有两个同名的不同属性。如果要重写它,则需要使基本属性virtual并在继承的类上使用override关键字:

代码语言:javascript
复制
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.CreatureCreature类型的。即使传入一个Cat,但由于Name属性没有被覆盖,所以调用Creature.Name。如果您已经重写了Name,那么将调用Cat.Name

票数 3
EN

Stack Overflow用户

发布于 2013-08-20 13:43:02

一个好的做法是阅读IDE给您的警告。

代码语言:javascript
复制
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.
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18336503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档