有可能重构这个C#if(..)语句吗?

时间:2010-04-03 11:24:59

标签: .net .net-4.0 refactoring if-statement

简单的问题: -

我有以下简单的if(..)语句: -

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

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

是否有可能将这些重构为...... ...

免责声明:我知道这不会编译..但这是我想要得到的...

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

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

干杯:)

修改

我想知道lambda表达式扩展是否可以做到这一点? :P

7 个答案:

答案 0 :(得分:13)

我通常创建一个名为IsIn()的扩展方法,它接受类型<T>的泛型参数数组,然后在其上调用.Contains(),传递调用扩展名的实例。< / p>

看起来像if (foo.IsIn(foo1, foo2))。编写非常简单,超级易用。

答案 1 :(得分:3)

在这种只有两个选项的特定情况下没有多大用处,但如果可能有很多选项,您可能更愿意将选项放在列表中,然后像这样使用Contains

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

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

此方法也适用于enums以外的其他类型,包括您无法switch开启的类型。如果只允许在运行时知道允许值列表,那么它也很有用。

请注意,如果每次出现性能损失时都会创建一个新列表。

答案 2 :(得分:2)

您可以使用Extension方法:

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

用法:

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

答案 3 :(得分:1)

您可以使用switch进行穿透(C语法的丑陋遗产):

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

但是,这只适用于这些微不足道的例子,而且我建议在这种情况下坚持if

答案 4 :(得分:1)

我对.NET 4.0并不是很了解(现在使用3.5),但我认为没有办法实现Pure.Krome想要的效果。

但是,通过使用LINQ提供的数组和扩展方法,可以实现对这种比较的近似。

这是一个小例子。

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

输出:

bingo string
bingo int

这种方式比简单的比较链和逻辑运算符更多的资源吞噬,但提供类似于Pure.Krome想要得到的语法。

如果您不想使用new []定义数组(在逻辑条件下它真的很有用),您可以为此定义自己的扩展方法。

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

所以你可以使用这个扩展方法:

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

输出真的可以预测,呵呵。

答案 5 :(得分:0)

这样做的另一种方法是分离规则&amp;当任何/所有这些都是真的时需要执行的逻辑:

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
}

然后,您可以通过.Any()和/或All()来使用规则来执行相关操作,例如:

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

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

HTH

答案 6 :(得分:0)

我认为一个更好的问题是为什么还要担心这件事呢?它很明显。我敢打赌,如果您发布了更多代码,那么还有许多其他事情需要先解决。