简体   繁体   中英

C# - Get switch value if in default case

Help please, I have this case:

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

As you can see the switch gets the value directly from a method without saving it as a variable.

Is it possible to get which value fires the default case? For example if MyFoo() returns 7, how can I get that value?

I want to avoid to save the method result as a variable, is there a way to get the switch value from inside a case? Something like this:

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

Thank you for reading, ~Saba

Is there a way to get the switch value from inside a case?

The only (proper) way is actually to store the result of MyFoo() in a variable.

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

This code is readable and understandable and have no extra cost (As @SheldonNeilson says: It's on the stack anyway).

Also, the MSDN first example about switch totally look like this. You can also find informations int the language specification .

You also can make your own switch based on a dictionary , but the only advantage I see is that you can use it for complex cases (any kind of object instead of string/int/...). Performance is a drawback.

It may look like this:

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;
    }
}

And be used like this:

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"

Or based on this response , this:

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);
        }
    }
}

Can be used like that:

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));

I can't see a reason as well why to use it like that but may be a work around will be like this:

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;
}

No, this isn't possible. You can assign the value to variable inside switch, if you want to look like reinventing the wheel:

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

The easiest way is to save the result of MyFoo() as a variable.. But if you don't want to do that you could do:

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

Although I would advise against this and say save the value as a variable to save your program the extra work.

Saving the value of MyFoo as a variable becomes more important the more complex the example gets as the value of MyFoo could have changed between the switch and default case.

Also this will only work where MyFoo has no side-effects and obviously must always return the same value for any given parameter.

for example the following would work:

Private int MyFoo()
{
   return 3;
}

But the following would not:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM