在C#中组合多个条件表达式

23
在C#中,有没有一种方法将if(index == 7 || index == 8)合并? 我想到了这样的写法:if(index == (7, 8))

你想要实现什么目标?是让它更易读,还是更简洁? - agent-j
两者都可以。有很多相等条件会占用比应该更多的空间。更紧凑的版本将提供更清晰的代码,而不会失去可读性。 - Andrew
1
重复的问题:我能在C#中使用linq压缩if语句吗? - Callum Rogers
9个回答

55
你可以通过扩展方法来实现这一点。
public static bool In<T>(this T obj, params T[] collection) {
   return collection.Contains(obj);
}

Then...

if(index.In(7,8))
{
    ...
}

+1 这非常好。我不知道这是否过度了,但它很花哨!希望我能点赞两次。 - Adriano Carneiro
1
+1 非常酷的解决方案。可能过于复杂(特别是对于只有两个数字的列表而言),但真的很酷。 - Coeffect
1
这绝对会进入我的扩展方法库。 - Adriano Carneiro
有趣的解决方案,但在许多情况下可能会很昂贵。 - kabuko
3
虽然这是一个聪明的解决方案,但我不禁认为它a) 过度杀伤力且过于昂贵,b) 没有解决为什么在原始问题中会出现这么多“魔术数”比较的根本问题。 - Dan Diplo
1
+1 不错的解决方案。每个人都担心过度设计和使用文字常量,但应该考虑到 OP 给出了一个普遍问题的简单示例。此外,如果发现问题,可以测量和调整性能,但我认为这个例程在绝大多数情况下都能够达到可接受的范围。 - JeremyDWill

9

您可以将需要比较的值放入内联数组中,并使用Contains扩展方法。请参见此文章以了解更多信息。

以下是几个演示该概念的代码片段:

int index = 1;
Console.WriteLine("Example 1: ", new int[] { 1, 2, 4 }.Contains(index));

index = 2;
Console.WriteLine("Example 2: ", new int[] { 0, 5, 3, 4, 236 }.Contains(index));

输出:

Example 1: True
Example 2: False

2
我更喜欢这个答案,因为很明确。但是当我查看我的代码中的常量列表时,我会想它们是否可以提取到其他系统中。仅有一些任意数字(甚至是枚举)的清单是一个糟糕的代码气味。 - Bill K
@Bill K:我同意,就目前而言,我的片段不适合用于生产。它的目的是尽可能清晰地展示概念。对于生产,我建议使用具有有意义名称的常量数组。 - Paul Sasik
像这样一组数值的数组意味着某种永久性——每当你有这样一个数字列表时,它们很可能会发生改变,应该成为数据。如果这是从文件中读入的"validCodes",那么情况就会突然变得有趣,但在这种情况下,你的解决方案是完美的。 - Bill K

3

据我所知,在当前的C#语法集中,没有办法将多个右操作数组合成一个传递给单个二进制运算符。


不是答案,对寻找答案没有帮助。 - SQLMason
@Dan Andrews,所以“不可能”不是一个答案吗?我非常确定语法上没有办法结合单个比较运算符使用多个操作数。您上面的答案在比较的事物类型不同时并没有帮助到我。 - Jeff Hubbard
@Jeff:很抱歉你感到不满。但是你的回答没有帮助找到解决方案,也没有提出建议。你应该只是发表评论。你关于使用多个操作数的评论表明你没有理解问题。 - SQLMason
2
首先,我并不生气。我理解你为什么说我的答案不是一个答案,但我不同意你的逻辑。这里有一个区别。然而,你假设我没有理解问题——我完全理解了——这是无效的。据我所知,在当前的C#语法集中,没有办法将多个RHS操作数组合成一个二元运算符传递。对于一些非常特定的类型,有一些非常具体的解决方法,但从长远来看这并不实用。我会编辑我的答案,以更清楚地表达我的意思。 - Jeff Hubbard
2
问题是...已经有一些答案了。可能在“x == 6,7”格式中技术上不可行,但是对于问题的意图已经有了答案。“那不可能因为FOO,但是这是你要求的做法..做BAR”会是一个好的答案。“那不可能”是一个没用的回答,不能帮助解决问题。 - WernerCD
这就是为什么我修改了我的答案,使其尽可能具体的原因。 - Jeff Hubbard

2

编写自己的扩展方法,这样您就可以编写

if (index.Between(7, 8)) {...}

where Between的定义如下:

    public static bool Between (this int a, int x, int y)
    {
        return a >= x && a <= y;
    }

我猜你提到扩展方法得分是+4,因为你的解决方案没有做到问题所要求的。 :) - SQLMason
虽然这个扩展方法肯定很有用,但问题是如何组合多个条件,而不是确定值是否在某个范围内。 - Jeromy Irvine

2
您可以使用以下内容:
 if (new List<int>() { 7, 8 }.Contains(index))

2
与其简短地提及使用列表来满足检查两个数字的过度夸张,我将写一个相当冗长的段落,需要更多的阅读努力,只是为了传达同样的观点:使用列表不会以任何方式比仅在两个条件中比较变量更简洁,精练或高效。 - Brad Christie
@Brad:他可能有20个条件。何必把所有的都写出来呢? - Ed Bayiates
1
@AresAvatar:因为列表是资源过度使用。而且,在多个数字比较的情况下,存在case语句。--编辑:我不会投反对票,因为这是一个可行的选择,只是使用大锤来挂画有点过度了。 - Brad Christie
@Brad:是否过度使用是由程序员决定的最佳决策,而不是你为这个例子做出的决定,而且我们也可以将列表(或数组)设为静态。我们正在建设性地回答问题的发帖人,而你没有。 - Ed Bayiates
@Brad,我不反对你的一般前提,但我不同意一个值列表在数组或列表中比条件或情况语句的字符串更可读或方便。无论如何,这归结为方便和可能的可读性与创建额外垃圾之间的权衡。(在仅有两个值的示例中,请务必使用or)。 - Anthony Pegram
显示剩余2条评论

2
switch (GetExpensiveValue())
{
case 7: case 8:
   // do work
   break;
}

这显然需要更多的代码,但它可能会避免您多次评估一个函数。

1
if ((new int[]{7,8}).Contains(index))

这个答案是错误的。它没有结合多个条件表达式,而是通过调用完全不同的方法来避免它们,这可能会在边缘情况下无法编译甚至给出不同的答案。(如果使用除 int 以外的类型,则一般情况下可能会有不同的答案)。这只是想说,从一个不清楚的问题开始,任何答案都可能是错误的! - Rotsor
1
他不需要多个条件表达式,并且在问题中也从未提到过。由于所选的正确答案与此非常相似,我担心您的评论是错误的。我的答案是作者预期的问题的解决方案。您因为不允许多个条件表达式而对我进行投票的原因是错误的。哦,好吧。 - SQLMason
如果您阅读问题的标题,您会发现作者要求组合多个条件表达式。此外,我不知道负评的假设是从哪里来的。 - Rotsor
整个线程都是一场灾难。错误的答案被投票支持,正确的答案却没有人点赞,昂贵的答案被大量点赞,现在作者决定给自己一个正确的答案...但它是错的,因为它是按位计算的。 - SQLMason

0

你需要类似这样的东西吗?

        int x = 5; 

        if((new int[]{5,6}).Contains(x)) 
        {
            Console.WriteLine("true");


        }
        Console.ReadLine();

0

没有直接的方法可以做到这一点,但你可以使用 if( index >=7 && index <= 8 ) 来进行范围判断。但如果要给它一个数字列表,你需要创建一个数组或列表对象,然后使用相应的方法来实现。但这有点过度设计了。


虽然肯定不如48klocs的那么棒,但我认为这个答案没有问题。没有办法在不创建列表/方法的情况下完成这个任务。48kloc的答案确实很优雅,但从性能上来看,它非常糟糕。 - Coeffect
你的答案是使用一个范围。问题是针对像SQL中的IN子句。我没有给你投反对票,只是认为你没有在问题的范围内回答,所以不值得+3分。除非你误解了问题的范围... - SQLMason

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接