【问题标题】:How to execute all statement except one based on some condition?如何根据某些条件执行除一条语句之外的所有语句?
【发布时间】:2019-01-27 17:06:36
【问题描述】:

假设我有一个方法,其中有多个语句将在调用除一个之外的方法时执行。 (根据传递给方法的参数决定不执行的语句)。

我怎样才能实现上述场景?

到目前为止我所做的事情。

我有以下方法。

enum Abc
{
    A = 0,
    B = 1,
    C = 2,
    D = 3,
    E = 4,
}
int GetSum(Abc abc)
{
    int sum = 0;
    if(abc != Abc.A)
    {
        sum += 23;
    }
    if(abc != Abc.B)
    {
        sum += 68;
    }
    if(abc != Abc.C)
    {
        sum += 96;
    }
    if(abc != Abc.D)
    {
        sum += 57;
    }
    if(abc != Abc.E)
    {
        sum += 63;
    }
    return sum;
}

在向sum 添加值之前,我正在根据abc 的值检查是否必须添加。

基本上,我希望如果abc 的值为Abc.A,则执行除sum += 23; 之外的所有语句。

在我的代码中,if 条件太多。有没有办法用更少的 if 语句或任何其他方式(更好)来做事?

注意:-这里sum += //something只是语句之一,语句不一定是加法(它可以是任何东西)。

【问题讨论】:

标签: c# if-statement conditional-statements


【解决方案1】:

@PeterB 的类似答案,但仅适用于您的总和示例:

int Method(Abc abc)
{
    Dictionary<Abc, int> dictionary = new Dictionary<Abc, int>()
    {
        { Abc.A, 23 },
        { Abc.B, 68 },
        { Abc.C, 96 },
        { Abc.D, 57 },
        { Abc.E, 63 }
    };

    return dictionary
        .Where(kvp => kvp.Key != abc)  // filter where Abc is different
        .Sum(kvp => kvp.Value);        // sum all values after filtering
}

@PeterB 的回答非常棒,并且可以轻松修改您的字典(新值、删除或修改一个值),甚至更改要执行的工作。
如果您只想总结您的值,我的只是提供了一个“小”快捷方式。

【讨论】:

    【解决方案2】:

    您可以使用包含Action 对象的Dictionary(委托的现代变体):

    int GetSum(Abc abc)
    {
        int sum = 0;
        var actionDict = new Dictionary<Abc, Action>
            {
                { Abc.A, () => sum += 23 },
                { Abc.B, () => sum += 68 },
                { Abc.C, () => sum += 96 },
                { Abc.D, () => sum += 57 },
                { Abc.E, () => sum += 63 }
            };
    
        foreach (var key in actionDict.Keys)
            if (key != abc) actionDict[key]();
    
        return sum;
    }
    

    请注意,对于字典,.Keys 的顺序是不可预测的。

    对于可预测的顺序,您需要使用 KeyValuePairs 的集合,如下所示:

    int GetSum(Abc abc)
    {
        int sum = 0;
        var actions = new List<KeyValuePair<Abc, Action>>
        {
            KVP(Abc.A, () => sum += 23),
            KVP(Abc.B, () => sum += 68),
            KVP(Abc.C, () => sum += 96),
            KVP(Abc.D, () => sum += 57),
            KVP(Abc.E, () => sum += 63)
        };
    
        foreach (var action in actions)
            if (action.Key != abc) action.Value();
    
        return sum;
    }
    
    KeyValuePair<Abc, Action> KVP(Abc x, Action y)
    {
        return new KeyValuePair<Abc, Action>(x, y);
    }
    

    【讨论】:

    • 请注意List&lt;KeyValuePair&lt;Abc, Action&gt;&gt; 也允许重复。
    • Action 与其说是代表的“现代变体”,不如说是处理代表的一种方式(如果它们与特定签名匹配)
    【解决方案3】:

    一般来说,您要求的是 switch 声明的相反;这不是一回事。我还要说,您关于“ifs 太多”的说法是主观的;如果这是要求,那么您所拥有的是一种相当简单的实现方式,我必须有一个具体的理由想要一个“更聪明”(即“更难阅读”)的解决方案。

    但在您列出的特定案例中,您可以颠倒逻辑,然后使用常规的switch 语句。

    int GetSum(Abc abc)
    {    
        int sum = 307; //23 + 68 + 96 + 57 + 63
        switch (abc) {
            case Abc.A:
                sum -= 23;
                break;
            case Abc.B:
                sum -= 68;
                break;
            // etc.
        }
        return sum;
    }
    

    显然,如果单个语句更复杂,以至于您不能“从末尾开始”并反转逻辑 - 特别是如果每​​个语句都有副作用 - 那么这种方法将不适用。但是,在更复杂的情况下,可能还有其他一些更有意义的模式。 (很可能包括 if 语句的运行。)

    【讨论】:

    • 多么巧合 - 计算器上的总数为 307!
    • 由于这些值似乎不是标志,我什至只是预先计算一个数组并将枚举值用作索引。
    • @Fildor - 也许吧。要看。如果其中一个值要更改,那将更难更新代码。 (使用预先计算的数组,您必须更改 5 或 6 件事。使用上面显示的反向逻辑开关,有 2 件事。使用原始实现 OP 不需要,只有 的 1 件事确实改变了。)这就是我需要一个聪明的理由的意思,这就是为什么这个问题可能受到过度简化(以排除更复杂的设计的地步)解决方案)
    • 完全同意。
    猜你喜欢
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 2016-11-02
    相关资源
    最近更新 更多