johnnie
johnnie

Reputation: 2057

Switch case in C# - a constant value is expected

public static void Output<T>(IEnumerable<T> dataSource) where T : class
{   
    dataSourceName = (typeof(T).Name);
    switch (dataSourceName)
    {
        case (string)typeof(CustomerDetails).Name.ToString(); :
            var t = 123;
            break;
        default:
            Console.WriteLine("Test");
    }
}

Why is the case statement giving an error that a constant variable is expected?

Upvotes: 133

Views: 264806

Answers (9)

Allen
Allen

Reputation: 590

This does require the latest or close to latest version of C#. The advantage is that the variable 'value' in this example can be manipulated, like this,

   switch (args[1])

                {
                    case var value when string.Equals(value, "SELECT_ALL", StringComparison.OrdinalIgnoreCase):
{
....
break;
}
   case var value when string.Equals(value, "UNSELECT_ALL", StringComparison.OrdinalIgnoreCase):

                        {
...
...
break;
}

etc. etc.

which makes sure that you never match to the wrong literal, in this case, because you forgot to use ToUpper() or whatever...

Upvotes: 0

MjH
MjH

Reputation: 1570

There is this trick which was shared with me (don't ask for details - won't be able to provide them, but it works for me):

switch (variable_1)
{
    case var value when value == variable_2: // that's the trick
        DoSomething();
        break;
    default:
        DoSomethingElse();
        break;
}

Upvotes: 102

0xF
0xF

Reputation: 3708

Now you can use nameof:

public static void Output<T>(IEnumerable<T> dataSource) where T : class
{
    string dataSourceName = typeof(T).Name;
    switch (dataSourceName)
    {
        case nameof(CustomerDetails):
            var t = 123;
            break;
        default:
            Console.WriteLine("Test");
    }
}

nameof(CustomerDetails) is basically identical to the string literal "CustomerDetails", but with a compile-time check that it refers to some symbol (to prevent a typo).

nameof appeared in C# 6.0, so after this question was asked.

Upvotes: 42

Maximilian Mayerl
Maximilian Mayerl

Reputation: 11357

You can only match to constants in switch statements.


Example:

switch (variable1)
{
    case 1: // A hard-coded value
        // Code
        break;
    default:
        // Code
        break;
}

Successful!


switch (variable1)
{
    case variable2:
        // Code
        break;
    default:
        // Code
        break;
}

CS0150 A constant value is expected.

Upvotes: 45

Korey
Korey

Reputation: 379

This seems to work for me at least when i tried on visual studio 2017.

public static class Words
{
     public const string temp = "What";
     public const string temp2 = "the";
}
var i = "the";

switch (i)
{
  case Words.temp:
    break;
  case Words.temp2:
    break;
}

Upvotes: 12

iDevForFun
iDevForFun

Reputation: 988

You can't use a switch statement for this as the case values cannot be evaluated expressions. For this you have to use an an if/else ...

public static void Output<T>(IEnumerable<T> dataSource) where T : class
{   
    dataSourceName = (typeof(T).Name);
    if(string.Compare(dataSourceName, typeof(CustomerDetails).Name.ToString(), true)==0)
    {
        var t = 123;
    }
    else if (/*case 2 conditional*/)
    {
        //blah
    }
    else
    {
        //default case
        Console.WriteLine("Test");
    }
}

I also took the liberty of tidying up your conditional statement. There is no need to cast to string after calling ToString(). This will always return a string anyway. When comparing strings for equality, bare in mind that using the == operator will result in a case sensitive comparison. Better to use string compare = 0 with the last argument to set case sensitive on/off.

Upvotes: 14

AksharRoop
AksharRoop

Reputation: 2293

Johnnie, Please go through msdn guide on switch. Also, the C# language specification clearly defines the compile time error case:

• If the type of the switch expression is sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, string, or an enum-type, or if it is the nullable type corresponding to one of these types, then that is the governing type of the switch statement.

• Otherwise, exactly one user-defined implicit conversion (§6.4) must exist from the type of the switch expression to one of the following possible governing types: sbyte, byte, short, ushort, int, uint, long, ulong, char, string, or, a nullable type corresponding to one of those types.

• Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.

Hope this helps.

Upvotes: 3

Jesus Ramos
Jesus Ramos

Reputation: 23268

switch is very picky in the sense that the values in the switch must be a compile time constant. and also the value that's being compared must be a primitive (or string now). For this you should use an if statement.

The reason may go back to the way that C handles them in that it creates a jump table (because the values are compile time constants) and it tries to copy the same semantics by not allowing evaluated values in your cases.

Upvotes: 3

deepee1
deepee1

Reputation: 13196

See C# switch statement limitations - why?

Basically Switches cannot have evaluated statements in the case statement. They must be statically evaluated.

Upvotes: 59

Related Questions