C # 中的开关情况-期望一个常量值

我的代码如下:

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

但这样不行。Case 语句给出了一个错误,说明应该使用常量变量。帮帮忙,谢谢你们!

213582 次浏览

C# switch statement limitations - why?

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

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.

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.

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.

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.

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

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.

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

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...