web-dev-qa-db-fra.com

Switch case in C # - une valeur constante est attendue

Mon code est le suivant:

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

Mais ça ne fonctionne pas. La déclaration de cas me donne une erreur en disant qu'une variable constante est attendue. S'il vous plaît aider les gars merci!

49
johnnie

Voir Limitations des instructions de commutateur C # - pourquoi?

En gros, les commutateurs ne peuvent pas avoir d'instructions évaluées dans l'instruction case. Ils doivent être évalués statiquement.

30
deepee1

Vous ne pouvez faire correspondre les constantes que dans les instructions switch.


Exemple:

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

Réussi!


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

CS015 Une valeur constante est attendue.

27
Maximilian Mayerl

Vous ne pouvez pas utiliser d'instruction switch pour cela car les valeurs de casse ne peuvent pas être des expressions évaluées. Pour cela, vous devez utiliser un 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");
    }
}

J'ai également pris la liberté de ranger votre déclaration conditionnelle. Il n'est pas nécessaire de transtyper en chaîne après avoir appelé ToString(). Cela retournera toujours une chaîne de toute façon. Lorsque vous comparez des chaînes pour vérifier leur égalité, gardez à l'esprit que l'utilisation de l'opérateur == entraînera une comparaison sensible à la casse. Il vaut mieux utiliser string compare = 0 avec le dernier argument pour activer/désactiver la casse.

8
iDevForFun

Johnnie, veuillez consulter le guide msdn sur switch . De plus, la spécification du langage C # définit clairement le cas d'erreur de compilation:

• Si le type de l'expression de commutateur est sbyte, octet, short, ushort, int, uint, long, ulong, bool, char, string ou un type enum, ou s'il s'agit du type nullable correspondant à l'un de ces types , alors c’est le type qui gouverne l’instruction switch.

• Sinon, il doit exister exactement une conversion implicite définie par l'utilisateur (§6.4) entre le type de l'expression de commutateur et l'un des types suivants: sbyte, byte, short, ushort, int, uint, long, ulong, char, etc. chaîne, ou un type nullable correspondant à l'un de ces types.

• Sinon, s'il n'existe pas de conversion implicite de ce type ou s'il en existe plusieurs, une erreur de compilation survient.

J'espère que cela t'aides.

3
AksharRoop

Cela semble fonctionner pour moi au moins quand j'ai essayé sur 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;
}
3
Korey

switch est très pointilleux en ce sens que les valeurs dans le switch doivent être une constante de temps de compilation. De plus, la valeur comparée doit être une primitive (ou une chaîne maintenant). Pour cela, vous devez utiliser une instruction if.

La raison peut revenir à la façon dont C les traite, dans la mesure où il crée une table de saut (car les valeurs sont des constantes de compilation) et tente de copier la même sémantique en n'autorisant pas les valeurs évaluées dans vos cas.

3
Jesus Ramos

Vous pouvez maintenant utiliser 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) est fondamentalement identique au littéral de chaîne "CustomerDetails", mais vérifie à la compilation qu'il fait référence à un symbole (pour éviter une faute de frappe).

nameof est apparu en C # 6.0, donc après cette question a été posée.

1
0xF