【问题标题】:Return value based on multiple bool conditions基于多个布尔条件的返回值
【发布时间】:2017-05-24 23:38:12
【问题描述】:

我有以下情况:

enum values{
go = 1,
stand = 2,
jump = 3,
run = 4,
go_stand=5,
go_jump=6,
go_run=7,
go_stand_jump=8,
… and so on 
Go_stand_jum_prun=17}

int select value(bool go, bool stand, bool jump, bool run)
{
}

基于传递给方法的 bool 值的组合,我需要返回适当的值,这意味着如果 go=true 其余为 false 1 如果传入的所有参数都为 true 将返回 17 将返回,同样适用于所有之间的组合。我唯一的想法是用很多 if 和 else if 语句来评估可能的组合,这有点难看。问题是有更优雅的解决方案。

谢谢大家!!!

【问题讨论】:

  • 这应该是什么语言?肯定不是C#...
  • 能否详细说明问题?你应该返回什么值?你写的函数是一个虚空。
  • 枚举与布尔值有什么关系?你能说明你如何使用布尔值吗?
  • 我需要返回合适的值什么是合适的值?你的方法签名也是错误的。
  • 您是否考虑过使用基于[Flags]enum 可能会简化事情?

标签: c# .net


【解决方案1】:

要实现这一点,您必须修改您的 enum

enum values {
    none = 0,
    go =  ( 1 << 0 ), // 1
    stand = ( 1 << 1 ), // 2
    jump =  ( 1 << 2 ), // 4,
    run = ( 1 << 3 ), // 8
    go_jump = go | jump
}

然后在你的方法中:

values GetValues(bool go, bool stand, bool jump, bool run)
{
    values result = values.none;
    if( go )
        result |= values.go;

    if( stand )
        result |= values.stand;

    // and so on...

    return result;
}

【讨论】:

  • 你不得不承认它在 1978 年更容易,但还是要投赞成票。
  • 您应该使用 Flags 属性。 msdn.microsoft.com/en-us/library/…
  • 如果您在 .net 中将枚举作为位字段使用,那么没有 flags 属性是不正确的。如果您检查我的答案,您会发现您不必手动定义枚举值的每个组合,但输出仍然显示单独的字段Console.WriteLine(value2); //Stand, Jump, Run。枚举必须声明所有可能的组合这一事实使其更容易出错(客观地)和可读性降低(主观地)。
  • @AndyJ 我不得不承认我的解决方案是“Anty-Idot”解决方案,因为您必须了解有关位运算符的一些知识,并且您必须指定您无法使用 FlagsAttribute 的所有可能组合。对于某些示例,可以使用FlagsAttribute,但我怀疑您是否可以使用stand | jump...
  • 我喜欢使用移位运算符来演示实际情况,而不仅仅是使用 1、2、4、8。
【解决方案2】:

您可以使用flags enum 来允许将这些值组合成一个枚举值。

表示可以将枚举视为位域;也就是一组标志。

这是一个例子: (Dot Net Fiddle)

using System;

[Flags]
public enum Value
{
    None = 0,
    Go = 1,
    Stand = 2,
    Jump = 4,
    Run = 8
}

public class Program
{
    public static void Main()
    {   
        var value1 = CreateValue(true, false, true, false);
        var value2 = CreateValue(false, true, true, true);

        Console.WriteLine(value1); //Go, Jump
        Console.WriteLine(value2); //Stand, Jump, Run
    }

    public static Value CreateValue(bool go, bool stand, bool jump, bool run)
    {
        var value = Value.None;

        if(go)
            value |= Value.Go;

        if(stand)
            value |= Value.Stand;

        if(jump)
            value |= Value.Jump;

        if(run)
            value |= Value.Run;

        return value;
    }
}

【讨论】:

  • 你错过了go_stand_jump 和其他标志
  • @Toshi -- 不。重新阅读答案。并阅读链接标志 MSDN。
  • @Toshi Flags 属性处理这个问题。如果您运行代码(按照 DotNetFiddle 链接),您将看到控制台输出值的内容。 value2 是“站立、跳跃、奔跑”。
【解决方案3】:

您可以使用逐位数学。例如,这是您的课程:

class MyClass
{
    [Flags]
    public enum Values
    {
        Go = 1,
        Stand = 2,
        Jump = 4,
        Run = 8
    }

    public Values Select(bool go, bool stand, bool jump, bool run)
    {
        Values ret = 0;
        if (go) ret = (ret | Values.Go);
        if (stand) ret = (ret | Values.Stand);
        if (jump) ret = (ret | Values.Jump);
        if (run) ret = (ret | Values.Run);
        return ret;
    }
}

下面是你如何使用它:

var mc = new MyClass();
MyClass.Values y = mc.Select(true, false, true, true);
bool isStand = (y & MyClass.Values.Stand) == MyClass.Values.Stand; // false
bool isJump = (y & MyClass.Values.Jump) == MyClass.Values.Jump; // true

【讨论】:

  • 我要问为什么是 2、4、8 和 64 而不是更传统的 1、2、4、8?
  • 谁知道呢。我猜只是我的标准。从来没有考虑太多。
  • 另外,我刚刚注意到您返回的是 int 而不是 enum。这是因为您不熟悉标志枚举(我​​认为是这样,但您可能有更好的理由使用 int 代替)?
  • 另一个好处是在 locals/autos/watch 窗口中。它显示实际值,而不仅仅是 int 值。
  • 我很想知道 DV 的用途……虽然每个人都有 DV,所以它可能是一个巨魔……
【解决方案4】:
public enum MyEnum
{
    Nothing = 0,
    Run = 1,
    Jump = 2,
    Stand = 4,
    Go = 8,
    RunJump = Run + Jump,
    RunStand = Run + Stand,
    ...
}

public MyEnum GetValue(bool go, bool stand, bool jump, bool run)
{
    // true, true, true, true is 1111
    // true, true, true, false is 1110
    var returnValue = (go ? 1 << 3 : 0) + (stand ? 1 << 2 : 0) + (jump ? 1 << 1 : 0) + (run ? 1 : 0);

    return (MyEnum)returnValue;
}

【讨论】:

    【解决方案5】:

    FlagsAttribute 应用于您的枚举:

    [Flags]
    public enum Activity
    {
        None = 0,
        Go = 1,
        Stand = 2,
        Jump = 4,
        Run = 8,
    }
    

    并利用conditional operator 来构造您的枚举:

    public static Activity CreateActivity(bool go, bool stand, bool jump, bool run)
    {
        return
            (go    ? Activity.Go    : 0) |
            (stand ? Activity.Stand : 0) |
            (jump  ? Activity.Jump  : 0) |
            (run   ? Activity.Run   : 0);
    }
    

    完整示例:

    using System;
    
    public class Program
    {
        public static void Main()
        {
            Activity goJump = Activity.Go | Activity.Jump;
    
            Activity activity =
                CreateActivity(
                    go:    true,
                    stand: false,
                    jump:  true,
                    run:   false);
    
            Console.WriteLine(activity == goJump); // prints "True"
        }
    
        public static Activity CreateActivity(bool go, bool stand, bool jump, bool run)
        {
            return
                (go    ? Activity.Go    : 0) |
                (stand ? Activity.Stand : 0) |
                (jump  ? Activity.Jump  : 0) |
                (run   ? Activity.Run   : 0);
        }
    }
    
    [Flags]
    public enum Activity
    {
        None = 0,
        Go = 1,
        Stand = 2,
        Jump = 4,
        Run = 8,
    }
    

    【讨论】:

      【解决方案6】:

      如果您排列未“正确”显示的值(如果它们不是以 0 而不是 1 开头),则此伪代码应该可以工作。..

      int select value(bool go, bool stand, bool jump, bool run)
       {
        return (int) runx2^3 + (int)jumpx2^2 + (int) standx2^1 + (int) go;
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-11
        • 2018-11-29
        • 1970-01-01
        • 1970-01-01
        • 2011-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多