web-dev-qa-db-fra.com

Quelle est la différence et pourquoi Switch Case fonctionne-t-il ainsi en C #?

J'ai deux fonctions, l'une peut être compilée et l'autre pas. Quelle est la différence?

La fonction numéro 1 suppose-t-elle que le cas 1 sera toujours atteint, ou s'agit-il simplement d'un problème de compilation?

public void Test(int x)
{
    switch (x)
    {
        case 1:
            uint cId = (uint)3;
            break;

        case 2:
            cId = (uint)5; //NO ERROR HERE. WHY?
            break;
    }
}

public void DeclaringInsideSwitch(int x)
{
    uint tst = 0;
    switch (x)
    {
        case 1:
            int y = 3;
            uint variable = tst;
            break;

        case 2:
            variable++; //ERROR HERE. WHY?
            break;
    }
}

J'ai essayé bien sûr de rechercher "Déclarer des variables à l'intérieur du boîtier de commutateur en C #", mais pour moi, cela ressemble à une sorte de bogue en C # maintenant, conservé pour une compatibilité descendante.

// Après avoir reçu un avertissement indiquant qu'il a déjà été répondu, ma question peut maintenant être réduite à ce dont il s'agit vraiment.

Pourquoi:

int x;
x++;

ça ne marche pas?

24
justromagod

Bien, uint cId est défini dans {...}scope ce qui est dans votre cas switch scope

switch (x)
{
    case 1:
        uint cId = (uint)3; // <- definition 
        break;

    case 2:
        // cId has been defined and thus can be assigned (initialization)
        cId = (uint)5; //NO ERROR HERE WHY?
        break;
}  // <- end of cId scope

Dans le second cas variable est défini, mais étant variable locale doit être initialisé avant utilisation (incrément):

switch (x)
{
    case 1:
        int y = 3;
        uint variable = tst; // <- definition 
        break;
    case 2:
        // variable defined, but has not been initialized ("case 1:" hasn't been run),
        // variable contains trash and so you can't increment it 
        variable++; //ERROR HERE WHY?
        break;
} // <- end of variable scope
17
Dmitry Bychenko

Fondamentalement, la déclartion variable est effectivement plus large que vous ne le pensez; le deuxième exemple souffre d'une "affectation définitive" car il est déclaré (plus large), mais pas réellement affecté, donc ++ n'a aucun sens sur une valeur non affectée.

Si vous voulez étendues par case, vous pouvez le faire ... ajoutez simplement des accolades:

        switch (x)
        {
            case 1:
            {
                uint cId = (uint)3;
                break;
            }
            case 2:
            {
                uint cId = (uint)5;
                break;
            }
        }

Est-ce un peu vexant? Oui. Est-ce anti-intuitif? Oui. Sera-t-il jamais changé? Peu probable, car ce serait un changement de rupture significatif qui empêcherait la compilation de beaucoup de C # existants.

24
Marc Gravell