更好的方法将两个不同的类与/同一基类放在同一个列表中?

时间:2011-07-26 15:34:15

标签: c# inheritance

假设我有一个名为BaseClass的基类:

public BaseClase{
    public bool isCool;
}

现在假设我有两个继承自BaseClass

的类
public Class1: BaseClass{
    public bool isGreen;
}

public Class2: BaseClass{
    public bool isPurple;
}

现在假设我想通过创建List创建一个包含Class1和Class2实例的列表;

var genericList = new List<BaseClass>();

接下来,让我们将一个Class1和Class2的实例添加到genericList。

genericList.Add(new Class1());
genericList.Add(new Class2());

现在,我有一个问题。如果我想访问Class1.IsGreen或Class2.IsPurple,我必须将genericList中的每个项目转换为Class1或Class2。

foreach(var item in genericList){
    if(item is Class1){
        var temp = (Class1) item;
        temp.IsGreen = true;
    }
    if(item is Class2){
        var temp = (Class2) item;
        item.IsPurple = true;
    }
}

这只是你应该做的事情吗?这对我来说似乎非常笨重,而我正在编写的使用这种代码结构的代码的复杂性已经失控。我是继承人的新手,想要了解这是否就是你应该做的事情,或者是否有更好的选择。

5 个答案:

答案 0 :(得分:2)

这实际上取决于你想要做什么。如果您可以抽象出属性,例如IsSelected,那么您可以将它作为虚拟或抽象属性在BaseClass上公开。然后你就不必在for-loop中投射你的物品了。

或者您可以将其抽象为抽象/虚拟方法,例如UpdateColor(bool)。然后每个派生类都可以覆盖它并在它们自己上设置适当的属性。

还有其他几种选择,包括接口和扩展方法,您可以使用它们使其更清洁。

答案 1 :(得分:1)

基本上没有更好的选择,但如果您只想操作,比如说Class1,那么您可以使用OfType扩展名

var genericList = new List<BaseClass>();
genericList.Add(new Class1());
genericList.Add(new Class2());

foreach(var item in genericList.OfType<Class1>())
{
  // no need to cast
  item.IsGreen = true;
}

答案 2 :(得分:1)

如果你能以某种方式abstarct在循环中做什么,例如,你正在为一个项目应用默认颜色,所以公开方法IEntity.SetDefaultColors(IColorInformation)并在每个项目类中实现它。

BTW:考虑Interface segregation principle并为IEntity等实体引入一个通用界面。

答案 3 :(得分:0)

我会说这样的话, 伪代码!

public sbstract BaseClase{
    public bool isCool;
    public abstract setColor();
}

public Class1: BaseClass{
    public bool isGreen;

    public override void SetColor() {IsGreen=true;}
}

public Class2: BaseClass{
    public bool isPurple;
    public override void SetColor() {IsPurple =true;}
}

foreach(var item in genericList){
    item.SetColor();
}

应该工作..

问候。

答案 4 :(得分:0)

为了更好(或更糟)地说明,我将把IsGreen更改为IsSpecial并将IsPurple更改为MaximumHappiness - 这样我们就可以清楚地知道这两个属性代表两种非常不同的东西。

处理它的一种方法是将它们作为基类的属性(如果适用),这样就不必对它们进行类型转换。

另一种方法是为基类提供一个函数(继承类可以覆盖它)。例如,该函数可以称为“DoSpecialThing”,在其中可以访问子类的任何属性。

如果保证属性是布尔值(并表示一些相关的想法),那么您可以使用标志。例如:

[Flags]
enum MoodType
{
    //Moods
    Happy,
    Sad,
    Elated,
    Overjoyed,
    Depressed,

    //Mental States
    Confused,
    Alert,
    Sluggish,

    //Other
    Sleepy,
    Awake
}

所以现在基类可以有一个名为“State”的属性,它可以是上述标志的任意组合。因此,您可以在一个属性中指示对象是Sleepy,Confused和Happy。

您可以阅读有关旗帜的更多信息(并确定它们是否适用于您的情况)at this link

我也推荐this SO question。特别是最高投票(虽然不被接受)的答案。