简体   繁体   中英

Avoiding messy flow control on boolean property lists in C#

We have an object of type MyObject which has several possible boolean values which we'll call Foo, Bar and Meh.

I have a list of other objects of the same type, and I only wish to select those which have a matching Foo/Bar/Meh value to the original. One way of doing so would be something like this:

List<MyObject> myObjects;

if(MyObject.Foo == true) {
    myObjects = existingMyObjects.Where(o => o.Foo == true).ToList();
}
else if(MyObject.Bar == true) {
    myObjects = existingMyObjects.Where(o => o.Bar == true).ToList();
}
else if(MyObject.Meh == true) {
    myObjects = existingMyObjects.Where(o => o.Meh == true).ToList();
}

Which is fine, but looks a bit of a mess.

In the real world, I have a similar situation except I'm dealing with nine of these boolean properties and have several instances where logic similar to above needs to live inside outer if/else statements.

That's going to be nigh-on unreadable. Is there a neater/simpler way of dealing with structures like this?

You can combine them in the Where() :

myObjects = existingMyObjects.Where(o => o.Foo == MyObject.Foo
                                      && o.Bar == MyObject.Bar
                                      && o.Meh == MyObject.Meh).ToList();

You could also override Equals() on your MyObject type:

public class MyObject
{
    public bool Foo { get; set; }
    public bool Bar { get; set; }
    public bool Meh { get; set; }

    public MyObject()
    {
    }

    public override bool Equals(object obj)
    {
        var item = obj as MyObject;

        if (item == null)
        {
            return false;
        }

        return (item.Foo == this.Foo && item.Bar == this.Bar && item.Meh == this.Meh);
    }

    public override int GetHashCode()
    {
        return new { Foo, Bar, Meh }.GetHashCode();
    }
}

You could then do:

var filtered = myObjects.Where(o => obj.Equals(o)).ToList();

Though your question lacks clarity. Do you want all objects that equal the original as you state or do you want all object where Foo/Bar/Meh are true as your code illustrates?

You could combine them all into one linq statement but whilst it is certainly fewer lines of code, I'm not sure it is any less of a mess!

List<MyObject> myObjects = existingMyObjects.Where(o => 
    (MyObject.Foo && o.Foo == true) ||
    (MyObject.Bar && o.Bar ) ||
    (MyObject.Meh && o.Meh == true)).ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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