Pure.Krome
Pure.Krome

Reputation: 86937

Is it possible to refactor this C# if(..) statement?

simple question :-

i have the following simple if (..) statements :-

if (foo == Animal.Cat || foo == Animal.Dog)
{ .. }

if (baa == 1|| baa == 69)
{ .. }

is it possible to refactor these into something like ...

DISCLAIMER: I know this doesn't compile .. but this is sorta what i'm trying to get...

if (foo == (Animal.Cat || Animal.Dog))
{ .. }

if (baa == (1 || 69))
{ .. }

Cheers :)

EDIT

I wonder if a lambda expression extension could do this? :P

Upvotes: 7

Views: 448

Answers (7)

Sunny
Sunny

Reputation: 6336

One more way of doing this is by separating out the rules & the logic which needs to be performed when any/all of them are true by:

var animal_rules = new Func<Animal, bool>[]{
 (a) => a == Animal.Cat,
 (a) => a == Animal.Dog
};

var baa_rules = new Func<int, bool>[]{
 (b) => b == 1,
 (b) => b == 69
}

Then, you can consume the rule by the .Any() and/or All() to do the relevant operations like:

if(animal_rules.Any(rule => rule(foo)){
 // animal logic here...
}

if(baa_rules.Any(rule => rule(baa)){
 // baa logic here...
}

HTH

Upvotes: 0

Larry Watanabe
Larry Watanabe

Reputation: 10184

I think a better question is why bother worrying about this at all? It is clear as it stands. I bet if you posted more of your code there would be many other things that should be addressed first.

Upvotes: 0

Eskat0n
Eskat0n

Reputation: 937

I don't really know much about .NET 4.0 (using 3.5 for now) but I think there are no way to achieve effect Pure.Krome want.

But approximation to this kind of comparing can be achieved by using arrays and extension methods LINQ provides.

Here is the little example.

string foo = @"very weird";
if (new[] { @"don't do it", @"very weird" }.Contains(foo))
{
    Console.WriteLine(@"bingo string");
}
int baa = 7;
if (new []{5, 7}.Contains(baa))
{
    Console.WriteLine(@"bingo int");
}

This outputs:

bingo string
bingo int

This way is more resource devouring than simple chain of comparsions and logical operators but provides syntax similar to one Pure.Krome wants to get.

If you are don't want to define arrays with new[] (it's really kinda ungly in logical conditions) you can define yourself extension method for this.

public static class Extensions
{
    public static bool IsOneOf<T>(this T obj, params T[] args)
    {
        return args.Contains(obj);
    }
}

So you can use this extension method:

if (baa.IsOneOf(5, 7, 9, 10))
{
    Console.WriteLine(@"bingo int");
}

Output is really predictable, heh.

Upvotes: 1

Mark Byers
Mark Byers

Reputation: 838066

It's not much use in this specific case where you only have two options, but if there could be many options you might prefer to put the options in a list and then use Contains like this:

List<Animal> allowedAnimals = new List<Animal>
{
    Animal.Cat,
    Animal.Dog,
    Animal.Fish,
    Animal.Frog,
    Animal.Horse
};

if (allowedAnimals.Contains(animal))
{
    // etc...
}

This method will also work on other types than enums including types that you cannot switch on. It is also useful if the list of allowed values will only be known at runtime.

Note that if you create a new list each time there will be a performance penalty.

Upvotes: 3

Stormenet
Stormenet

Reputation: 26468

You could use an Extension method for that:

public static bool IsAny<T>(this Enum value, params T[] values)
        {
            foreach (T e in values)
            {
                if (value.Equals(e)) return true;
            }
            return false;
        }

usage:

enum TestEnum
    {
        Stackoverflow,
        overflowStack,
        stackstack
    }

TestEnum val = TestEnum.overflowStack;

Console.WriteLine(val.IsAny(TestEnum.stackstack, TestEnum.Stackoverflow));  //false
Console.WriteLine(val.IsAny(TestEnum.overflowStack, TestEnum.Stackoverflow)); // true

Upvotes: 2

Seth Petry-Johnson
Seth Petry-Johnson

Reputation: 12085

I usually create an extension method called IsIn() that takes a generic parameter array of type <T> and then calls .Contains() on it, passing the instance on which the extension is called.

It looks like if (foo.IsIn(foo1, foo2)). Very simple to write, super easy to use.

Upvotes: 13

Joey
Joey

Reputation: 354406

You can use switch with fallthrough (an ugly heritage of C syntax):

switch (foo) {
    case Animal.Cat:
    case Animal.Dog:
    {
        ...
        break;
    }
}

Will only work for such trivial examples, though, and I'd suggest sticking to if in that case anyway.

Upvotes: 1

Related Questions