Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的多变量switch语句#_C#_.net_Switch Statement_Logic_Switch Expression - Fatal编程技术网

C# C语言中的多变量switch语句#

C# C语言中的多变量switch语句#,c#,.net,switch-statement,logic,switch-expression,C#,.net,Switch Statement,Logic,Switch Expression,我想使用一个switch语句,它包含几个变量,如下所示: switch (intVal1, strVal2, boolVal3) { case 1, "hello", false: break; case 2, "world", false: break; case 2, "hello", false: etc .... } switch (first + last) { cas

我想使用一个switch语句,它包含几个变量,如下所示:

switch (intVal1, strVal2, boolVal3)
{
   case 1, "hello", false:
      break;
   case 2, "world", false:
      break;
   case 2, "hello", false:

   etc ....
}
switch (first + last)
{
   case "ClarkKent":
   case "LoisLane":
      // YES
      break;
   default;
      // Sadly, no
      break;
}
在C#中有没有这样的方法?(出于明显的原因,我不想使用嵌套的switch语句)

net开发团队通过实现这一可怕的事实回答了这个问题:

据我所知,在C#中无法做到这一点

但您可以从MSDN执行此操作:

以下示例显示,空案例标签允许从一个案例标签跌落到另一个案例标签:

 switch(n) 
        {
            case 1:
            case 2: 
            case 3: 
                Console.WriteLine("It's 1, 2, or 3.");
                break; 
        default: 
            Console.WriteLine("Not sure what it is.");
            break; 
        }
根据C语言规范,
开关
语句表达式必须解析为以下表达式之一。这意味着您不能打开
元组
或其他高阶类型

假设有空间,您可以尝试将这些值打包在一起。例如,假设每个整数都保证在0..9范围内

switch (intVal1 * 100 + intVal2 * 10 + (boolVal3 ? 1 : 0))
{
case 100: /* intVal1 = 1, intVal2 = 0, boolVal3 = false */ ... break;
case 831: /* intVal1 = 8, intVal2 = 3, boolVal3 = true */ ... break;
}
在C#中没有内置的功能来实现这一点,我也不知道有哪个库可以实现这一点

下面是另一种方法,使用
元组
和扩展方法:

using System;

static class CompareTuple {
    public static bool Compare<T1, T2, T3>(this Tuple<T1, T2, T3> value, T1 v1, T2 v2, T3 v3) {
        return value.Item1.Equals(v1) && value.Item2.Equals(v2) && value.Item3.Equals(v3); 
    }
}

class Program {
    static void Main(string[] args) {
        var t = new Tuple<int, int, bool>(1, 2, false);
        if (t.Compare(1, 1, false)) {
            // 1st case
        } else if (t.Compare(1, 2, false)) {
            // 2nd case
        } else { 
            // default
        }
    }
}
使用系统;
静态类比较器偶{
公共静态布尔比较(此元组值,T1 v1、T2 v2、T3 v3){
返回值.Item1.Equals(v1)和&value.Item2.Equals(v2)和&value.Item3.Equals(v3);
}
}
班级计划{
静态void Main(字符串[]参数){
var t=新元组(1,2,false);
if(t.Compare(1,1,false)){
//第一例
}else if(t.比较(1,2,false)){
//第2例
}否则{
//违约
}
}
}

这基本上就是提供一种方便的语法来检查多个值,并使用多个
if
s而不是
开关来检查多个值

class Program
{
    static void Main(string[] args)
    {
        var i = 1;
        var j = 34;
        var k = true;
        Match(i, j, k).
            With(1, 2, false).Do(() => Console.WriteLine("1, 2, 3")).
            With(1, 34, false).Do(() => Console.WriteLine("1, 34, false")).
            With(x => i > 0, x => x < 100, x => x == true).Do(() => Console.WriteLine("1, 34, true"));

    }

    static Matcher<T1, T2, T3> Match<T1, T2, T3>(T1 t1, T2 t2, T3 t3)
    {
        return new Matcher<T1, T2, T3>(t1, t2, t3);
    }
}

public class Matcher<T1, T2, T3>
{
    private readonly object[] values;

    public object[] Values
    {
        get { return values; }
    }

    public Matcher(T1 t1, T2 t2, T3 t3)
    {
        values = new object[] { t1, t2, t3 };
    }

    public Match<T1, T2, T3> With(T1 t1, T2 t2, T3 t3)
    {
        return new Match<T1, T2, T3>(this, new object[] { t1, t2, t3 });
    }

    public Match<T1, T2, T3> With(Func<T1, bool> t1, Func<T2, bool> t2, Func<T3, bool> t3)
    {
        return new Match<T1, T2, T3>(this, t1, t2, t3);
    }
}

public class Match<T1, T2, T3>
{
    private readonly Matcher<T1, T2, T3> matcher;
    private readonly object[] matchedValues;
    private readonly Func<object[], bool> matcherF; 

    public Match(Matcher<T1, T2, T3> matcher, object[] matchedValues)
    {
        this.matcher = matcher;
        this.matchedValues = matchedValues;
    }

    public Match(Matcher<T1, T2, T3> matcher, Func<T1, bool> t1, Func<T2, bool> t2, Func<T3, bool> t3)
    {
        this.matcher = matcher;


        matcherF = objects => t1((T1)objects[0]) && t2((T2)objects[1]) && t3((T3)objects[2]);
    }

    public Matcher<T1, T2, T3> Do(Action a)
    {
        if(matcherF != null && matcherF(matcher.Values) || matcher.Values.SequenceEqual(matchedValues))
            a();

        return matcher;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var i=1;
var j=34;
var k=真;
匹配(i,j,k)。
使用(1,2,false).Do(()=>Console.WriteLine(“1,2,3”))。
使用(1,34,false).Do(()=>Console.WriteLine(“1,34,false”))。
使用(x=>i>0,x=>x<100,x=>x==true).Do(()=>Console.WriteLine(“1,34,true”);
}
静态匹配器匹配(T1、T2、T3)
{
返回新匹配器(t1、t2、t3);
}
}
公共类匹配器
{
私有只读对象[]值;
公共对象[]值
{
获取{返回值;}
}
公共匹配器(T1、T2、T3)
{
值=新对象[]{t1,t2,t3};
}
公共比赛(T1、T2、T3)
{
返回新的匹配项(这个,新对象[]{t1,t2,t3});
}
公共匹配(功能t1、功能t2、功能t3)
{
返回新的匹配项(this、t1、t2、t3);
}
}
公开课比赛
{
私有只读匹配器匹配器;
私有只读对象[]匹配值;
私有只读函数匹配器;
公共匹配(匹配器匹配器,对象[]匹配值)
{
this.matcher=matcher;
this.matchedValues=matchedValues;
}
公共匹配(匹配器匹配器、功能t1、功能t2、功能t3)
{
this.matcher=matcher;
matcherF=objects=>t1((t1)objects[0])&&t2((t2)objects[1])&&t3((t3)objects[2]);
}
公共匹配器Do(动作a)
{
if(matcherF!=null&&matcherF(matcher.Values)| | matcher.Values.SequenceEqual(matchedValues))
a();
返回匹配器;
}
}

让我们从另一个角度来看这个问题。如果您有:

  • 要检查的非常具体的组合
  • 没有比较可以做
  • 每个不匹配案例的默认处理程序
  • 所有基元/值类型(
    int
    bool
    string
    等)
然后可以使用查找表,该表的执行速度与
switch
语句相似,但效率不高(因为它需要计算哈希)。不过,这可能已经足够好了。它让你有机会命名案例,让这个组合爆炸稍微少一些混乱和不可维护

代码示例:

private static readonly Tuple<int, int, bool> NameOfCase1 = 
    Tuple.Create(1, 1, false);
private static readonly Tuple<int, int, bool> NameOfCase2 =
    Tuple.Create(2, 1, false);
private static readonly Tuple<int, int, bool> NameOfCase3 =
    Tuple.Create(2, 2, false);

private static readonly Dictionary<Tuple<int, int, bool>, string> Results =
    new Dictionary<Tuple<int, int, bool>, string>
{
    { NameOfCase1, "Result 1" },
    { NameOfCase2, "Result 2" },
    { NameOfCase3, "Result 3" }
};

public string GetResultForValues(int x, int y, bool b)
{
    const string defaultResult = "Unknown";
    var lookupValue = Tuple.Create(x, y, b);
    string result;
    Results.TryGetValue(lookupValue, out result);
    return defaultResult;
}
Case1的私有静态只读元组名称=
创建(1,1,false);
Case2的私有静态只读元组名称=
创建(2,1,false);
Case3的私有静态只读元组名称=
创建(2,2,false);
私有静态只读字典结果=
新词典
{
{NameOfCase1,“结果1”},
{NameOfCase2,“结果2”},
{NameOfCase3,“结果3”}
};
公共字符串GetResultForValues(整数x、整数y、布尔b)
{
常量字符串defaultResult=“未知”;
var lookupValue=Tuple.Create(x,y,b);
字符串结果;
结果.TryGetValue(查找值,输出结果);
返回默认结果;
}
如果需要为每种情况实际执行函数或方法,则可以使用
Action
Func
的结果类型(字典值)


请注意,我在这里使用的是
Tuple
,因为它已经内置了所有哈希代码逻辑。C语言中的语法有点笨拙,但是如果您愿意,您可以实现自己的查找类,只需覆盖
Equals
GetHashCode
,我就可以使用列表或数组来执行这种操作。如果您可以枚举可能的条件(如果您想进行多值切换,显然可以枚举),然后使用多部分键和
Action
Func
作为值构建一个查找表

简单版本将使用
词典

class LookupKey: IComparable<LookupKey>
{
    public int IntValue1 { get; private set; }
    public int IntValue2 { get; private set; }
    public bool BoolValue1 { get; private set; }
    public LookupKey(int i1, int i2, bool b1)
    {
        // assign values here
    }
    public int Compare(LookupKey k1, LookupKey k2)
    {
        return k1.IntValue1 == k2.IntValue1 &&
               k1.IntValue2 == k2.IntValue2 &&
               k1.BoolValue1 == k2.BoolValue1;
    }
    public int GetHashCode()
    {
        return (19 * IntValue1) + (1000003 * IntValue2) + (BoolValue1) ? 0 : 100000073;
    }
    // need to override Equals
}
类查找键:IComparable
{
public int IntValue1{get;private set;}
public int IntValue2{get;private set;}
公共布尔布尔值1{get;私有集;}
公共查找键(int i1、int i2、bool b1)
{
//在此处赋值
}
公共整数比较(查找键k1、查找键k2)
{
返回k1.IntValue1==k2.IntValue1&&
k1。
static readonly Dictionary<LookupKey, Action<object>> LookupTable;
Action<object> MethodToCall;
if (LookupTable.TryGetValue(new LookupKey(i1, i2, b1), out MethodToCall)
    MethodToCall(theData);
else
    // default action if no match
switch (intVal1.ToString() + strVal2 + boolVal3.ToString())
{
   case "1helloFalse":
      break;
   case "2worldFalse":
      break;
   case "2helloFalse":

   etc ....
}
switch (first + last)
{
   case "ClarkKent":
   case "LoisLane":
      // YES
      break;
   default;
      // Sadly, no
      break;
}
switch (intVal1)
{
    case 1 when strVal2 == "hello" && boolVal3 == false:
        break;
    case 2 when strVal2 == "world" && boolVal3 == false:
        break;
    case 2 when strVal2 == "hello" && boolVal3 == false:
        break;
}
string result = (intVal1, strVal2, boolVal3) switch
{
    (1, "hello", false) => "Combination1",
    (2, "world", false) => "Combination2",
    (2, "hello", false) => "Combination3",
    _ => "Default"
};
public static string RockPaperScissors(string first, string second)
    => (first, second) switch
    {
        ("rock", "paper") => "rock is covered by paper. Paper wins.",
        ("rock", "scissors") => "rock breaks scissors. Rock wins.",
        ("paper", "rock") => "paper covers rock. Paper wins.",
        ("paper", "scissors") => "paper is cut by scissors. Scissors wins.",
        ("scissors", "rock") => "scissors is broken by rock. Rock wins.",
        ("scissors", "paper") => "scissors cuts paper. Scissors wins.",
        (_, _) => "tie"
    };
//.Net Core 3.1
    class Convertors
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Convertors.ConvertAny("m","cm", 10));
            Console.ReadKey();
        }
        public static double MToCM(double value)
        {
            return value * 100;
        }
        public static double ConvertAny(string srcUOM, string tgtUOM, double value)
        {
            switch (srcUOM.ToLower(), tgtUOM.ToLower())
            {
                case ("m", "cm"): return Convertors.MToCM(value);
                default: throw new NotImplementedException();
            }
        }
    }