开发者

Better Way To Put Two Different Classes w/ Same Base Class In Same List?

Let's say I have a base class named BaseClass:

public BaseClase{
    public bool isCool;
}

Now let's say I have two classes that inherit from BaseClass

public Class1: BaseClass{
    public bool isGreen;
}

public Class2: BaseClass{
    public bool isPurple;
}

Now let's say I want to create a list that contains instances of both Class1 and Class2 by creating a List;

var genericList = new List<BaseClass>();

Next, let's add an instance of Class1 and Class2 to genericList.

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

Now, here is what I have a question about. If I want to access Class1.IsGreen or Class2.IsPurple, I have to cast each item in genericList as Class1 or 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;
    }
}

Is this just the way you're supposed to do things? It seems very clunky to me, and the complexity of the code I'm writing that uses this type of code structure is getting out of hand. I'm new to inheritance, and want to learn if this is just the way you're supposed to do things, or if there are better alternatives out there.开发者_Python百科


It really depends on what you are trying to do. If you can abstract out the property, so something like IsSelected, then you could expose it on your BaseClass as a virtual or abstract property. Then you wouldn't have to cast your items in your for-loop.

Or you could abstract it out to a abstract/virtual method, like UpdateColor(bool). Then each derived class could override that and set the appropriate property on themselves.

There are several other alternatives, including interfaces and extension methods, that you could use to make it cleaner.


There is basically no better alternative, although if you only want to operate on, say Class1's then you can use the OfType extension

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;
}


If you can abstarct somehow what are you doing in the cycle, for instance, you are applying a Default colors for an item, so expose method IEntity.SetDefaultColors(IColorInformation) and implement it in each item class.

BTW: Consider the Interface segregation principle and introduce a common interface for you entities like IEntity.


To better (or worse) illustrate, I'm going to change IsGreen to IsSpecial and IsPurple to MaximumHappiness--just so that we can be clear that the two properties represent two very different things.

One way to handle it would be to make them both properties of the base class (if applicable), so then you don't have to typecast them.

Another would be to provide a function to the base class (which the inheriting classes could override). For instance, the function could be called "DoSpecialThing" and inside of it you can access any properties on the child classes.

If the properties are guaranteed to be boolean (and represent some amount of related ideas), then you might be able to use flags. For instance:

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

    //Mental States
    Confused,
    Alert,
    Sluggish,

    //Other
    Sleepy,
    Awake
}

So now the base class could have a property called "State" or something and it can be any combination of the above flags. So you could indicate that an object is Sleepy, Confused, and Happy all in one property.

You can read more about flags (and decide if they're applicable to your situation) at this link.

I'd recommend this SO question, too. Specifically the top-voted (although unaccepted) answer.


I would say somethign like this, pseudoecode!:

public abstract 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();
}

Should work..

Regards.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜