如何在C#中重写一个非常大的复合if语句?

时间:2022-09-06 19:21:22

In my C# code, I have an if statement that started innocently enough:

在我的C#代码中,我有一个非常开始的if语句:

if((something == -1) && (somethingelse == -1) && (etc == -1)) {
    // ...
}

It's growing. I think there must be 20 clauses in it now.

它正在增长。我认为现在必须有20个条款。

How should I be handling this?

我应该怎么处理这个?

18 个解决方案

#1


Use gates where possible.

尽可能使用大门。

the if statement

if语句

if(bailIfIEqualZero != 0 && 
   !string.IsNullOrEmpty(shouldNeverBeEmpty) &&
   betterNotBeNull != null &&
   !betterNotBeNull.RunAwayIfTrue &&
   //yadda

the refactored version

重构的版本

if(bailIfIEqualZero == 0)
  return;

if(string.IsNullOrEmpty(shouldNeverBeEmpty))
  return;

if(betterNotBeNull == null || betterNotBeNull.RunAwayIfTrue)
  return;

//yadda

#2


Factor it out into a function and make each condition a guard clause:

将其分解为函数并使每个条件成为保护条款:

int maybe_do_something(...) {
    if(something != -1)
        return 0;
    if(somethingelse != -1)
        return 0;
    if(etc != -1)
        return 0;
    do_something();
    return 1;
}

#3


Assuming all those conditions are really necessary, you could consolidate the conditions into one or more uber-booleans or function calls to enhance readability.

假设所有这些条件都是必要的,您可以将条件合并为一个或多个超级布尔值或函数调用以增强可读性。

E.g.,

bool TeamAIsGoForLaunch = BobSaysGo && BillSaysGo;
bool TeamBIsGoForLaunch = JillSaysGo && JackSaysGo;

if (TeamAIsGoForLaunch && TeamBIsGoForLaunch && TeamC.isGoForLaunch())

#4


One thing to consider is why you have so many clauses. Just as SWITCH statements often indicate that you should be moving the choices into subclasses, a large complex chain of IF statements can indicate that you are combining too many concepts (and thus decisions) in one place.

要考虑的一件事是为什么你有这么多条款。正如SWITCH语句通常表明您应该将选择移动到子类中一样,大型复杂的IF语句链可以表明您在一个地方组合了太多的概念(从而决策)。

As an example, I will use the example of calculating commission. In one system I built, the commission rate is dependent upon the amount of commission given to the wholesaler, who passes some on to the retailer. The amount given from a wholesaler to retailer depends on the specific agreement between the retailer and the wholesaler (based on a contract). The amount the wholesaler gets likewise depends on the product line, specific product and amount of the product sold.

作为一个例子,我将使用计算佣金的例子。在我建立的一个系统中,佣金率取决于批发商的佣金金额,批发商将一些交给零售商。从批发商到零售商的金额取决于零售商和批发商之间的具体协议(基于合同)。批发商获得的数量同样取决于产品线,特定产品和销售产品的数量。

Beyond this, there were additional "exception" rules based on the customer's state, specific product customizations, etc. This could all be worked out in a complex chain of IF statements, but we instead made the application data driven.

除此之外,还有基于客户状态,特定产品定制等的额外“异常”规则。这可以在复杂的IF语句链中解决,但我们改为驱动应用程序数据。

By putting all of this information into tables, we were then able to make passes on the data rules. First the wholesaler's generic rules would trigger and then any override rules would trigger. Then, having the base wholesaler commission in hand we would run the wholesaler to retailer generic rules and then the exceptions to those.

通过将所有这些信息放入表中,我们就可以传递数据规则。首先,批发商的通用规则将触发,然后任何覆盖规则将触发。然后,掌握基础批发商佣金,我们将批发商运行到零售商通用规则,然后是那些例外。

This turned a huge hairball of logic into a simple four step process, with each step simply making a database query to find the correct rule to apply.

这将一个巨大的逻辑毛球转变为一个简单的四步过程,每个步骤只需进行数据库查询即可找到要应用的正确规则。

This of course may not apply in your situation, but often a large complex like that really means that either there are not enough classes dividing up the responsibility (another solution to our problem could have been factory classes that contained the specific rules and overrides), or the functionality should be data driven.

这当然可能不适用于您的情况,但通常这样的大型复合体实际上意味着没有足够的类来划分责任(我们问题的另一个解决方案可能是包含特定规则和覆盖的工厂类),或者功能应该是数据驱动的。

#5


Refactor it to a function.

将其重构为函数。

bool Check()
{
  return (something == -1) && (somethingelse == -1) && (etc == -1);
}

Alternatively, you can build more readable code/logic in your Check function.

或者,您可以在Check函数中构建更易读的代码/逻辑。

#6


There are many ways to handle this, but let me pick a few.

有很多方法可以解决这个问题,但请允许我选择一些。

First, there's the case where all of the criteria (all of the AND-criteria in your if-statement) + the code to execute if they're all true is a one-off situation.

首先,所有标准(if语句中的所有AND标准)+如果它们都是真的则执行的代码是一次性情况。

In this case, use the code you have. You might want to do what several others have already suggested, rewrite to use a Guard-clause type of code.

在这种情况下,请使用您拥有的代码。您可能希望执行其他几个已经建议的操作,重写以使用Guard子句类型的代码。

In other words, instead of this:

换句话说,而不是这样:

if (a && b && c && d && ......)
    DoSomething();

... you rewrite to something similar to this:

...你重写了类似的东西:

if (!a) return;
if (!b) return;
if (!c) return;
if (!d) return;
if (!...) return;
DoSomething();

Why? Because once you start introducing OR-criteria into the mix, it gets hard to read the code and figure out what is going to happen. In the above code, you split the criteria on each AND-operator (&&), and thus the code becomes easier to read. Basically you rewrite the code from saying "if this and that, or that other thing and that third thing, or some other thing, then do something" to be "if this, then exit; if that other thing; then exit; if some other thing; then exit; if none of the above, do something".

为什么?因为一旦你开始在混合中引入OR标准,就很难阅读代码并弄清楚会发生什么。在上面的代码中,您在每个AND运算符(&&)上拆分条件,因此代码变得更容易阅读。基本上你重写代码来说“如果这个和那个,或那个其他的东西和那个第三件事,或者其他东西,然后做某事”是“如果这个,然后退出;如果那个其他的东西;然后退出;如果一些其他的东西;然后退出;如果以上都没有,做一些事情“。

However, in many cases, you also have the case of reusability. If some of those criteria appear else-where, but the code that will actually execute (DoSomething) isn't the same, then I'd go for, again, what others have already suggested. Rewrite the criteria into methods that return a Boolean result depending on the result of evaluating the criteria.

但是,在许多情况下,您还具有可重用性的情况。如果其中一些标准出现在其他地方,但实际执行的代码(DoSomething)并不相同,那么我会再次考虑其他人已经提出的建议。将条件重写为返回布尔结果的方法,具体取决于评估条件的结果。

For instance, what is easier to read, this?

例如,什么更容易阅读,这?

if (a && b && c && d && e && f && (h || i) && (j || k) || l)

or this:

if (CanAccessStream() && CanWriteToStream())

assuming all those letters can be split into those two criteria.

假设所有这些字母都可以分成这两个标准。

In that case I would take some of the criteria and put into those methods, and choose an appropriate name for the criteria.

在这种情况下,我会采用一些标准并加入这些方法,并为标准选择合适的名称。

The third option is where the criteria differs in several places in the code, but the actual code to execute is the same.

第三个选项是代码中的几个位置的条件不同,但实际执行的代码是相同的。

In this case I would rewrite so that you group criteria together and layer the methods so that calling one method will check some criteria, and then call another method, which will check some other criteria, etc.

在这种情况下,我会重写,以便您将标准组合在一起并对方法进行分层,以便调用一个方法将检查某些条件,然后调用另一个方法,这将检查其他一些标准,等等。

For instance, you could write this:

例如,你可以这样写:

if (stream != null && buffer != null && inBuffer > 0 && stream.CanWrite)
  stream.Write(buffer, 0, inBuffer);
else
    throw new InvalidOperationException();

or you could write this:

或者你可以这样写:

if (inBuffer > 0)
{
    Debug.Assert(buffer != null);
    WriteToStream(buffer, inBuffer);
}

...

private void WriteToStream(Byte[] buffer, Int32 count)
{
    if (stream.CanWrite)
        stream.Write(buffer, 0, count);
    else
        throw new InvalidOperationException();
}

I'd say the second way is easier to read, and is more reusable, than the first.

我会说第二种方式比第一种方式更易于阅读,并且更易于重复使用。

#7


You could refactor it as a function, and return an Enum value that represents the case that was true:

您可以将其重构为函数,并返回一个Enum值,该值表示为true的情况:

if(something != -1)
    return MyEnum.Something;
if(somethingelse != -1)
    return MyEnum.SomethingElse;
if(etc != -1)
    return MyEnum.SomethingElseEntirely;
return MyEnum.None;

#8


Perform aggregate operations on a list of your values.

在值列表上执行聚合操作。

if (new[] { something, somethingelse, ... }.All(x => x == -1)) {
}

*Edit: Givin' the data an extra-line:

*编辑:Givin'数据是一个额外的线:

var Data = new[] { something, somethingelse, ... };
if (Data.All(x => x == -1)) {
}

#9


It looks like you have 3 pieces of information that together represent a particular state in your application. Instead of switching on these 3 pieces of state, why not create a value that encapsulates them? Then you could use an object hierarchy or a delegate at creation time to bind the action you are trying to run.

看起来您有3条信息,它们共同代表您的应用程序中的特定状态。为什么不创建一个封装它们的值,而不是打开这3个状态?然后,您可以在创建时使用对象层次结构或委托来绑定您尝试运行的操作。

#10


You could also factor the state into a class.

您还可以将状态分解为一个类。

class mystate
{
    int something;
    int somethingelse;
    int etc;

    bool abletodostuff()
    {
        return (something == -1) && (somethingelse == -1) && (etc == -1);
    }
}

#11


I don't know C#, but it seems to include the conditional operator. If your conditions are short, you can replace long if/elsif/else chains with nice table-like structures, like this:

我不知道C#,但似乎包括条件运算符。如果您的条件很短,您可以使用漂亮的表格式结构替换long if / elsif / else链,如下所示:

return   something == 0      ? 0
       : somethingelse == -1 ? 1
       : yetanotherthing > 2 ? 2
       :                       3; # default

#12


Yet another avenue that you may explore is the use of composite expressions. These expressions (which are the basis of how LINQ works in the .NET framework) allows you to create expression trees based on all these conditions and then the business logic code can simply operate on the top level expression to get back the true/false result.

您可以探索的另一种途径是使用复合表达式。这些表达式(它是LINQ如何在.NET框架中工作的基础)允许您基于所有这些条件创建表达式树,然后业务逻辑代码可以简单地在*表达式上操作以获取真/假结果。

To evaluate the expressions, you can make use of the visitor pattern

要评估表达式,您可以使用访问者模式

This allows you to easily compose trees of the conditions. these trees can be serialized even to let you persist the conditions that you made the decision under. Lots of opportunities present themselves here.

这使您可以轻松地组成条件树。这些树可以被序列化,甚至可以让你坚持你做出决定的条件。这里有很多机会。

#13


It's not that common to see that many clauses in one "if". You usually find that you need to nest the "ifs" to get the logic you need, when you need to execute some line regardless of the truth of some conditions. I'm not saying nest them if you don't need to, if they all need to be tested at the same time. Only if there's some common functionality. Another consideration is to set a boolean variable with the result of some set of these conditions, that might make it easier to understand. If your variables are an array or collection, could you loop through them? Are you testing them all against -1?

在一个“如果”中看到许多条款并不常见。您通常会发现需要嵌套“ifs”以获得所需的逻辑,当您需要执行某些行时,无论某些条件的真实性如何。如果你不需要,我不是说嵌套它们,如果它们都需要同时进行测试的话。只有有一些共同的功能。另一个考虑因素是设置一个布尔变量,其中包含一些这些条件的结果,这可能使其更容易理解。如果你的变量是一个数组或集合,你可以循环它们吗?你是否对-1测试它们?

#14


While I like Dario's solution (as I commented, I'd put it in a boolean function so I didn't have to have a new in the condition part of an if...) I'm not sure what's wrong with:

虽然我喜欢Dario的解决方案(正如我评论的那样,我将它放在一个布尔函数中,所以我不必在if的条件部分有一个新的...)我不确定是什么问题:

if((something == -1) &&
   (somethingElse == -1) &&
   (elseElse == -1) &&
   ...
  )

I think that's probably a lot easier to read than a lot of ((A && B) || (C &&(D||E))) that I have to deal with...

我认为这可能比我必须处理的很多((A && B)||(C &&(D || E)))更容易阅读...

#15


I do this in a way nobody likes except me. I don't care if the code "looks good". If I've got >1 test in that conditional, that means I'm liable to want even more, or I may want to comment some of them in or out, and I want to simplify the making of such changes.

我这样做的方式除了我以外没有人喜欢。我不在乎代码“看起来不错”。如果我在那个条件下进行了> 1次测试,那意味着我可能想要更多,或者我可能想要对其中的一些进行评论,我想简化这些变更的制作。

So I code it like this:

所以我这样编码:

if (true
  && test_1
  && test_2
  ...
  )
{
  ...
}

This makes it easy to comment out tests, or add new ones, as 1-line edits.

这样可以轻松地将测试注释掉或添加新测试,作为1行编辑。

But I'll be the first to admit, it doesn't claim to be pretty.

但我会是第一个承认,它并不是说自己很漂亮。

#16


If you really have to check against all these conditions, you can't get rid of them. You can only refactor it and make it more readable, but the logic stays the same.

如果你真的要检查所有这些条件,你就无法摆脱它们。您只能重构它并使其更具可读性,但逻辑保持不变。

I'm quite surprised that no one has mentioned anything about redesigning your code. Do you really really need 20 differents states? In my experience, a lot of states are often depending on other states and are therefore often logically redundant to check against.

我很惊讶没有人提到有关重新设计代码的任何内容。你真的需要20个不同的州吗?根据我的经验,许多州通常依赖于其他州,因此在逻辑上往往是多余的以进行检查。

Refactoring your code might help you get a better understanding of it and how the states are coupled to each other. I'd start here first if I were you :)

重构代码可能有助于您更好地理解代码以及状态如何相互耦合。如果我是你,我先从这里开始:)

#17


And Something like this

还有像这样的东西

I'll explain a litlle further. (And fix the stupid errors :S)

我会进一步解释一下。 (并修复愚蠢的错误:S)

//Interface to be able to which classes are able to give a boolean result used in the if stuff
public interface IResultable
{
    bool Result();
}

//A list that is IResultable itself it gathers the results of the IResultables inside.
public class ComparatorList<T> : List<T>, IResultable where T : IResultable
{
    public bool Result()
    {
        bool retval = true;
        foreach (T t in this)
        {
            if (!t.Result())
            {
                retval = false;
            }
        }
        return retval;
    }
}

//Or two bools
public class OrComparator : IResultable
{
    bool left;
    bool right;

    public OrComparator(bool left, bool right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left || right);
    }

    #endregion
}

// And two bools
public class AndComparator : IResultable
{
    bool left;
    bool right;

    public AndComparator(bool left, bool right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left && right);
    }

    #endregion
}

// compare two ints
public class IntIsComparator : IResultable
{
    int left;
    int right;

    public IntIsComparator(int left, int right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left == right);
    }

    #endregion
}

Is you have a lot of there if statements this could be cool :)

如果声明这可能很酷,你有很多吗:)

So we have this sturcture for handeling a lot of comparisons. I'll give a little example implementation.

所以我们有这个结构来进行大量的比较。我将举一个例子实现。

//list of ands
ComparatorList<AndComparator> ands = new ComparatorList<AndComparator>();    
ands.Add(new AndComparator(true,true));

//list of ors
ComparatorList<OrComparator> ors = new ComparatorList<OrComparator>();
ors.Add(new OrComparator(false, true));

//list of intiss
ComparatorList<IntIsComparator> ints = new ComparatorList<IntIsComparator>();
ints.Add(new IntIsComparator(1, 1));

//list of all things :)
ComparatorList<IResultable> collected = new ComparatorList<IResultable>();
collected.Add(ands);
collected.Add(ors);
collected.Add(ints);

// if all things are as they must be :)
if (collected.Result())
{
    //Evertything is as it schould be :)
}

#18


you say you are looking at strings so how about something like this which someone commented about already.

你说你正在看字符串,所以有人这样评论已经有人这么说了。

        var items = new List<string>();

        items.Add("string1");
        items.Add("string2");

        if (items.Contains("string2"))
        {
            // do something
        }

you could even grab the values from a configuration file of some sort to populate the list.

你甚至可以从某种配置文件中获取值来填充列表。

#1


Use gates where possible.

尽可能使用大门。

the if statement

if语句

if(bailIfIEqualZero != 0 && 
   !string.IsNullOrEmpty(shouldNeverBeEmpty) &&
   betterNotBeNull != null &&
   !betterNotBeNull.RunAwayIfTrue &&
   //yadda

the refactored version

重构的版本

if(bailIfIEqualZero == 0)
  return;

if(string.IsNullOrEmpty(shouldNeverBeEmpty))
  return;

if(betterNotBeNull == null || betterNotBeNull.RunAwayIfTrue)
  return;

//yadda

#2


Factor it out into a function and make each condition a guard clause:

将其分解为函数并使每个条件成为保护条款:

int maybe_do_something(...) {
    if(something != -1)
        return 0;
    if(somethingelse != -1)
        return 0;
    if(etc != -1)
        return 0;
    do_something();
    return 1;
}

#3


Assuming all those conditions are really necessary, you could consolidate the conditions into one or more uber-booleans or function calls to enhance readability.

假设所有这些条件都是必要的,您可以将条件合并为一个或多个超级布尔值或函数调用以增强可读性。

E.g.,

bool TeamAIsGoForLaunch = BobSaysGo && BillSaysGo;
bool TeamBIsGoForLaunch = JillSaysGo && JackSaysGo;

if (TeamAIsGoForLaunch && TeamBIsGoForLaunch && TeamC.isGoForLaunch())

#4


One thing to consider is why you have so many clauses. Just as SWITCH statements often indicate that you should be moving the choices into subclasses, a large complex chain of IF statements can indicate that you are combining too many concepts (and thus decisions) in one place.

要考虑的一件事是为什么你有这么多条款。正如SWITCH语句通常表明您应该将选择移动到子类中一样,大型复杂的IF语句链可以表明您在一个地方组合了太多的概念(从而决策)。

As an example, I will use the example of calculating commission. In one system I built, the commission rate is dependent upon the amount of commission given to the wholesaler, who passes some on to the retailer. The amount given from a wholesaler to retailer depends on the specific agreement between the retailer and the wholesaler (based on a contract). The amount the wholesaler gets likewise depends on the product line, specific product and amount of the product sold.

作为一个例子,我将使用计算佣金的例子。在我建立的一个系统中,佣金率取决于批发商的佣金金额,批发商将一些交给零售商。从批发商到零售商的金额取决于零售商和批发商之间的具体协议(基于合同)。批发商获得的数量同样取决于产品线,特定产品和销售产品的数量。

Beyond this, there were additional "exception" rules based on the customer's state, specific product customizations, etc. This could all be worked out in a complex chain of IF statements, but we instead made the application data driven.

除此之外,还有基于客户状态,特定产品定制等的额外“异常”规则。这可以在复杂的IF语句链中解决,但我们改为驱动应用程序数据。

By putting all of this information into tables, we were then able to make passes on the data rules. First the wholesaler's generic rules would trigger and then any override rules would trigger. Then, having the base wholesaler commission in hand we would run the wholesaler to retailer generic rules and then the exceptions to those.

通过将所有这些信息放入表中,我们就可以传递数据规则。首先,批发商的通用规则将触发,然后任何覆盖规则将触发。然后,掌握基础批发商佣金,我们将批发商运行到零售商通用规则,然后是那些例外。

This turned a huge hairball of logic into a simple four step process, with each step simply making a database query to find the correct rule to apply.

这将一个巨大的逻辑毛球转变为一个简单的四步过程,每个步骤只需进行数据库查询即可找到要应用的正确规则。

This of course may not apply in your situation, but often a large complex like that really means that either there are not enough classes dividing up the responsibility (another solution to our problem could have been factory classes that contained the specific rules and overrides), or the functionality should be data driven.

这当然可能不适用于您的情况,但通常这样的大型复合体实际上意味着没有足够的类来划分责任(我们问题的另一个解决方案可能是包含特定规则和覆盖的工厂类),或者功能应该是数据驱动的。

#5


Refactor it to a function.

将其重构为函数。

bool Check()
{
  return (something == -1) && (somethingelse == -1) && (etc == -1);
}

Alternatively, you can build more readable code/logic in your Check function.

或者,您可以在Check函数中构建更易读的代码/逻辑。

#6


There are many ways to handle this, but let me pick a few.

有很多方法可以解决这个问题,但请允许我选择一些。

First, there's the case where all of the criteria (all of the AND-criteria in your if-statement) + the code to execute if they're all true is a one-off situation.

首先,所有标准(if语句中的所有AND标准)+如果它们都是真的则执行的代码是一次性情况。

In this case, use the code you have. You might want to do what several others have already suggested, rewrite to use a Guard-clause type of code.

在这种情况下,请使用您拥有的代码。您可能希望执行其他几个已经建议的操作,重写以使用Guard子句类型的代码。

In other words, instead of this:

换句话说,而不是这样:

if (a && b && c && d && ......)
    DoSomething();

... you rewrite to something similar to this:

...你重写了类似的东西:

if (!a) return;
if (!b) return;
if (!c) return;
if (!d) return;
if (!...) return;
DoSomething();

Why? Because once you start introducing OR-criteria into the mix, it gets hard to read the code and figure out what is going to happen. In the above code, you split the criteria on each AND-operator (&&), and thus the code becomes easier to read. Basically you rewrite the code from saying "if this and that, or that other thing and that third thing, or some other thing, then do something" to be "if this, then exit; if that other thing; then exit; if some other thing; then exit; if none of the above, do something".

为什么?因为一旦你开始在混合中引入OR标准,就很难阅读代码并弄清楚会发生什么。在上面的代码中,您在每个AND运算符(&&)上拆分条件,因此代码变得更容易阅读。基本上你重写代码来说“如果这个和那个,或那个其他的东西和那个第三件事,或者其他东西,然后做某事”是“如果这个,然后退出;如果那个其他的东西;然后退出;如果一些其他的东西;然后退出;如果以上都没有,做一些事情“。

However, in many cases, you also have the case of reusability. If some of those criteria appear else-where, but the code that will actually execute (DoSomething) isn't the same, then I'd go for, again, what others have already suggested. Rewrite the criteria into methods that return a Boolean result depending on the result of evaluating the criteria.

但是,在许多情况下,您还具有可重用性的情况。如果其中一些标准出现在其他地方,但实际执行的代码(DoSomething)并不相同,那么我会再次考虑其他人已经提出的建议。将条件重写为返回布尔结果的方法,具体取决于评估条件的结果。

For instance, what is easier to read, this?

例如,什么更容易阅读,这?

if (a && b && c && d && e && f && (h || i) && (j || k) || l)

or this:

if (CanAccessStream() && CanWriteToStream())

assuming all those letters can be split into those two criteria.

假设所有这些字母都可以分成这两个标准。

In that case I would take some of the criteria and put into those methods, and choose an appropriate name for the criteria.

在这种情况下,我会采用一些标准并加入这些方法,并为标准选择合适的名称。

The third option is where the criteria differs in several places in the code, but the actual code to execute is the same.

第三个选项是代码中的几个位置的条件不同,但实际执行的代码是相同的。

In this case I would rewrite so that you group criteria together and layer the methods so that calling one method will check some criteria, and then call another method, which will check some other criteria, etc.

在这种情况下,我会重写,以便您将标准组合在一起并对方法进行分层,以便调用一个方法将检查某些条件,然后调用另一个方法,这将检查其他一些标准,等等。

For instance, you could write this:

例如,你可以这样写:

if (stream != null && buffer != null && inBuffer > 0 && stream.CanWrite)
  stream.Write(buffer, 0, inBuffer);
else
    throw new InvalidOperationException();

or you could write this:

或者你可以这样写:

if (inBuffer > 0)
{
    Debug.Assert(buffer != null);
    WriteToStream(buffer, inBuffer);
}

...

private void WriteToStream(Byte[] buffer, Int32 count)
{
    if (stream.CanWrite)
        stream.Write(buffer, 0, count);
    else
        throw new InvalidOperationException();
}

I'd say the second way is easier to read, and is more reusable, than the first.

我会说第二种方式比第一种方式更易于阅读,并且更易于重复使用。

#7


You could refactor it as a function, and return an Enum value that represents the case that was true:

您可以将其重构为函数,并返回一个Enum值,该值表示为true的情况:

if(something != -1)
    return MyEnum.Something;
if(somethingelse != -1)
    return MyEnum.SomethingElse;
if(etc != -1)
    return MyEnum.SomethingElseEntirely;
return MyEnum.None;

#8


Perform aggregate operations on a list of your values.

在值列表上执行聚合操作。

if (new[] { something, somethingelse, ... }.All(x => x == -1)) {
}

*Edit: Givin' the data an extra-line:

*编辑:Givin'数据是一个额外的线:

var Data = new[] { something, somethingelse, ... };
if (Data.All(x => x == -1)) {
}

#9


It looks like you have 3 pieces of information that together represent a particular state in your application. Instead of switching on these 3 pieces of state, why not create a value that encapsulates them? Then you could use an object hierarchy or a delegate at creation time to bind the action you are trying to run.

看起来您有3条信息,它们共同代表您的应用程序中的特定状态。为什么不创建一个封装它们的值,而不是打开这3个状态?然后,您可以在创建时使用对象层次结构或委托来绑定您尝试运行的操作。

#10


You could also factor the state into a class.

您还可以将状态分解为一个类。

class mystate
{
    int something;
    int somethingelse;
    int etc;

    bool abletodostuff()
    {
        return (something == -1) && (somethingelse == -1) && (etc == -1);
    }
}

#11


I don't know C#, but it seems to include the conditional operator. If your conditions are short, you can replace long if/elsif/else chains with nice table-like structures, like this:

我不知道C#,但似乎包括条件运算符。如果您的条件很短,您可以使用漂亮的表格式结构替换long if / elsif / else链,如下所示:

return   something == 0      ? 0
       : somethingelse == -1 ? 1
       : yetanotherthing > 2 ? 2
       :                       3; # default

#12


Yet another avenue that you may explore is the use of composite expressions. These expressions (which are the basis of how LINQ works in the .NET framework) allows you to create expression trees based on all these conditions and then the business logic code can simply operate on the top level expression to get back the true/false result.

您可以探索的另一种途径是使用复合表达式。这些表达式(它是LINQ如何在.NET框架中工作的基础)允许您基于所有这些条件创建表达式树,然后业务逻辑代码可以简单地在*表达式上操作以获取真/假结果。

To evaluate the expressions, you can make use of the visitor pattern

要评估表达式,您可以使用访问者模式

This allows you to easily compose trees of the conditions. these trees can be serialized even to let you persist the conditions that you made the decision under. Lots of opportunities present themselves here.

这使您可以轻松地组成条件树。这些树可以被序列化,甚至可以让你坚持你做出决定的条件。这里有很多机会。

#13


It's not that common to see that many clauses in one "if". You usually find that you need to nest the "ifs" to get the logic you need, when you need to execute some line regardless of the truth of some conditions. I'm not saying nest them if you don't need to, if they all need to be tested at the same time. Only if there's some common functionality. Another consideration is to set a boolean variable with the result of some set of these conditions, that might make it easier to understand. If your variables are an array or collection, could you loop through them? Are you testing them all against -1?

在一个“如果”中看到许多条款并不常见。您通常会发现需要嵌套“ifs”以获得所需的逻辑,当您需要执行某些行时,无论某些条件的真实性如何。如果你不需要,我不是说嵌套它们,如果它们都需要同时进行测试的话。只有有一些共同的功能。另一个考虑因素是设置一个布尔变量,其中包含一些这些条件的结果,这可能使其更容易理解。如果你的变量是一个数组或集合,你可以循环它们吗?你是否对-1测试它们?

#14


While I like Dario's solution (as I commented, I'd put it in a boolean function so I didn't have to have a new in the condition part of an if...) I'm not sure what's wrong with:

虽然我喜欢Dario的解决方案(正如我评论的那样,我将它放在一个布尔函数中,所以我不必在if的条件部分有一个新的...)我不确定是什么问题:

if((something == -1) &&
   (somethingElse == -1) &&
   (elseElse == -1) &&
   ...
  )

I think that's probably a lot easier to read than a lot of ((A && B) || (C &&(D||E))) that I have to deal with...

我认为这可能比我必须处理的很多((A && B)||(C &&(D || E)))更容易阅读...

#15


I do this in a way nobody likes except me. I don't care if the code "looks good". If I've got >1 test in that conditional, that means I'm liable to want even more, or I may want to comment some of them in or out, and I want to simplify the making of such changes.

我这样做的方式除了我以外没有人喜欢。我不在乎代码“看起来不错”。如果我在那个条件下进行了> 1次测试,那意味着我可能想要更多,或者我可能想要对其中的一些进行评论,我想简化这些变更的制作。

So I code it like this:

所以我这样编码:

if (true
  && test_1
  && test_2
  ...
  )
{
  ...
}

This makes it easy to comment out tests, or add new ones, as 1-line edits.

这样可以轻松地将测试注释掉或添加新测试,作为1行编辑。

But I'll be the first to admit, it doesn't claim to be pretty.

但我会是第一个承认,它并不是说自己很漂亮。

#16


If you really have to check against all these conditions, you can't get rid of them. You can only refactor it and make it more readable, but the logic stays the same.

如果你真的要检查所有这些条件,你就无法摆脱它们。您只能重构它并使其更具可读性,但逻辑保持不变。

I'm quite surprised that no one has mentioned anything about redesigning your code. Do you really really need 20 differents states? In my experience, a lot of states are often depending on other states and are therefore often logically redundant to check against.

我很惊讶没有人提到有关重新设计代码的任何内容。你真的需要20个不同的州吗?根据我的经验,许多州通常依赖于其他州,因此在逻辑上往往是多余的以进行检查。

Refactoring your code might help you get a better understanding of it and how the states are coupled to each other. I'd start here first if I were you :)

重构代码可能有助于您更好地理解代码以及状态如何相互耦合。如果我是你,我先从这里开始:)

#17


And Something like this

还有像这样的东西

I'll explain a litlle further. (And fix the stupid errors :S)

我会进一步解释一下。 (并修复愚蠢的错误:S)

//Interface to be able to which classes are able to give a boolean result used in the if stuff
public interface IResultable
{
    bool Result();
}

//A list that is IResultable itself it gathers the results of the IResultables inside.
public class ComparatorList<T> : List<T>, IResultable where T : IResultable
{
    public bool Result()
    {
        bool retval = true;
        foreach (T t in this)
        {
            if (!t.Result())
            {
                retval = false;
            }
        }
        return retval;
    }
}

//Or two bools
public class OrComparator : IResultable
{
    bool left;
    bool right;

    public OrComparator(bool left, bool right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left || right);
    }

    #endregion
}

// And two bools
public class AndComparator : IResultable
{
    bool left;
    bool right;

    public AndComparator(bool left, bool right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left && right);
    }

    #endregion
}

// compare two ints
public class IntIsComparator : IResultable
{
    int left;
    int right;

    public IntIsComparator(int left, int right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left == right);
    }

    #endregion
}

Is you have a lot of there if statements this could be cool :)

如果声明这可能很酷,你有很多吗:)

So we have this sturcture for handeling a lot of comparisons. I'll give a little example implementation.

所以我们有这个结构来进行大量的比较。我将举一个例子实现。

//list of ands
ComparatorList<AndComparator> ands = new ComparatorList<AndComparator>();    
ands.Add(new AndComparator(true,true));

//list of ors
ComparatorList<OrComparator> ors = new ComparatorList<OrComparator>();
ors.Add(new OrComparator(false, true));

//list of intiss
ComparatorList<IntIsComparator> ints = new ComparatorList<IntIsComparator>();
ints.Add(new IntIsComparator(1, 1));

//list of all things :)
ComparatorList<IResultable> collected = new ComparatorList<IResultable>();
collected.Add(ands);
collected.Add(ors);
collected.Add(ints);

// if all things are as they must be :)
if (collected.Result())
{
    //Evertything is as it schould be :)
}

#18


you say you are looking at strings so how about something like this which someone commented about already.

你说你正在看字符串,所以有人这样评论已经有人这么说了。

        var items = new List<string>();

        items.Add("string1");
        items.Add("string2");

        if (items.Contains("string2"))
        {
            // do something
        }

you could even grab the values from a configuration file of some sort to populate the list.

你甚至可以从某种配置文件中获取值来填充列表。