C# - 如果是默认情况下获取切换值

时间:2015-04-14 13:22:33

标签: c# switch-statement

请帮忙,我有这个案子:

switch(MyFoo()){
    case 0: //...
        break;
    case 1: //...
        break;
    case 2: //...
        break;
    default:
        // <HERE>
        break;
}

正如您所看到的,交换机直接从方法获取值而不将其保存为变量。

是否可以获取触发default案件的值? 例如,如果MyFoo()返回7,我该如何获得该值?

我想避免将方法结果保存为变量,有没有办法从案例中获取开关值?像这样:

default:
    this.SwitchValue // <<--
    break;

感谢您的阅读, 〜萨巴

4 个答案:

答案 0 :(得分:12)

  

有没有办法从案例中获取开关值?

唯一(正确)方法实际上是将MyFoo()的结果存储在变量中。

var fooResult = MyFoo();
switch (fooResult)
{
    case 0:
        ...
        break;
    ...
    default:
        handleOthersCase(fooResult);
        break;
}

此代码易读且易懂,无需额外费用(正如@SheldonNeilson所说:无论如何都在堆栈中。)

此外,关于switch的MSDN第一个示例完全如下所示。您还可以在language specification

中找到信息

您还可以根据dictionary制作自己的开关,但我看到的唯一优势是您可以将它用于复杂的案例(任何一种对象而不是string / int / ...)。性能是一个缺点。

看起来像这样:

public class MySwitch<T> : Dictionary<T, Action<T>>
{
    private Action<T> _defaultAction;

    public void TryInvoke(T value)
    {
        Action<T> action;
        if (TryGetValue(value, out action))
        {
            action(value);
        }
        else
        {
            var defaultAction = _defaultAction;
            if (defaultAction != null)
            {
                defaultAction(value);
            }
        }
    }

    public void SetDefault(Action<T> defaultAction)
    {
        _defaultAction = defaultAction;
    }
}

可以像这样使用:

var mySwitch = new MySwitch<int>();

mySwitch.Add(1, i => Console.WriteLine("one"));                             // print "one"
mySwitch.Add(2, i => Console.WriteLine("two"));                             // print "two"
mySwitch.SetDefault(i => Console.WriteLine("With the digits: {0}", i));     // print any other value with digits.

mySwitch.TryInvoke(42);                                                     // Output: "With the digits: 42"

或基于this response,这个:

public class MySwitch2<T>
{
    private readonly T _input;

    private bool _done = false;

    private MySwitch2(T input)
    {
        _input = input;
    }

    public MySwitch2<T> On(T input)
    {
        return new MySwitch2<T>(input);
    }

    public MySwitch2<T> Case(T caseValue, Action<T> action)
    {
        if (!_done && Equals(_input, caseValue))
        {
            _done = true;
            action(_input);
        }
        return this;
    }

    public void Default(Action<T> action)
    {
        if (!_done)
        {
            action(_input);
        }
    }
}

可以这样使用:

MySwitch2<int>.On(42)
    .Case(1, i => Console.WriteLine("one"))
    .Case(2, i => Console.WriteLine("two"))
    .Default(i => Console.WriteLine("With the digits: {0}", i));

答案 1 :(得分:5)

我无法看到一个原因,为什么要这样使用它,但可能是一个解决方案将是这样的:

int x;
switch ( x = MyFoo())
{
    case 0: //...
        break;
    case 1: //...
        break;
    case 2: //...
        break;
    default:
        var s = x; // Access and play with x here
        break;
}

答案 2 :(得分:3)

不,这是不可能的。 如果要重新发明轮子,可以将值分配给变量内部开关:

        int b;
        .....
        switch (b = MyFoo())
        {
            case 1:
                break;
            case 2:
                break;
            default:
                //do smth with b
                break;
        }

答案 3 :(得分:1)

最简单的方法是将MyFoo()的结果保存为变量..但如果您不想这样做,您可以这样做:

switch(MyFoo()){
    case 0: //...
        break;
    case 1: //...
        break;
    case 2: //...
        break;
    default:
        this.SwitchCase = MyFoo();
        break;
}

虽然我会建议不要这样做,并说将值保存为变量,以节省您的程序额外的工作。

MyFoo的值保存为变量变得更加重要,因为MyFoo的值可能在切换和默认情况之间发生变化,因此示例变得越复杂

这仅适用于MyFoo是纯函数的情况。即返回给定参数的相同值

例如以下内容可行:

Private int MyFoo()
{
   return 3;
}

但以下不会:

private int MyFoo()
{
  Random r = new Random();
  return r.Next(5);
}