Variabele declaraties die volgen op if-statements

Er kwam een ​​probleem naar voren op een ander forum en ik wist hoe ik het moest oplossen, maar het onthulde een eigenschap van de compiler die speciaal voor mij was. De persoon kreeg de foutmelding “Ingesloten instructie kan geen verklaring of gelabelde instructie zijn” omdat ze een declaratie van een variabele hadden na een if-instructie zonder haakjes. Dat was niet hun bedoeling, maar ze hadden commentaar gegeven op de coderegel die onmiddellijk volgde op de if-instructie, waardoor de variabeledeclaratie de de facto regel code was die moest worden uitgevoerd. Hoe dan ook, dat is de achtergrond, die me hier brengt.

De volgende code is illegaal

if (true)
    int i = 7;

Als je dat echter tussen haakjes plaatst, is het allemaal legaal.

if (true)
{
    int i = 7;
}

Geen enkel stukje code is nuttig. Toch is de tweede oké. Wat is specifiek de verklaring voor dit gedrag?


Antwoord 1, autoriteit 100%

De C# taalspecificatieonderscheidt drie soorten statements (zie hoofdstuk 8 voor meer details). Over het algemeen kun je deze uitspraken hebben:

  • labeled-statement– ik vermoed dat dit voor de ouderwetse goto-statement is
  • declaration-statement– wat een variabele declaratie zou zijn
  • embedded-statement– dat vrijwel alle overige statements bevat

In het ifstatement moet de body embedded-statementzijn, wat verklaart waarom de eerste versie van de code niet werkt. Hier is de syntaxis van ifuit de specificatie (paragraaf 8.7.1):

if ( boolean-expression) embedded-statement
if ( boolean-expression) embedded-statementelse embedded-statement

Een variabele declaratie is declaration-statement, dus deze kan niet in de body verschijnen. Als u de verklaring tussen haakjes plaatst, krijgt u een instructieblok, dat een embedded-statementis (en dus kan het op die positie verschijnen).


Antwoord 2, autoriteit 33%

Als u de haakjes niet opneemt, wordt de volgende regel uitgevoerd alsof deze tussen haakjes staat. Omdat het niet veel zin heeft om een ​​variabele in die regel te declareren (je zou het nooit kunnen gebruiken), zal de C#-compiler dit niet toestaan ​​om te voorkomen dat je het per ongeluk doet zonder het te weten (wat subtiele bugs kan introduceren ).

Hier is een deel van Eric Lippert te zeggen over de C#-compiler op dit SO-antwoordover naamresolutie:

…C# is geen “raad eens wat de gebruiker”
bedoelde” taal … de compiler door
ontwerp klaagt luid als het beste is
match is iets dat niet werkt


Antwoord 3, autoriteit 12%

Alle compilers stellen je in staat om code te compileren die nutteloos is of extreem weinig gebruikt. Er zijn gewoon te veel manieren waarop een ontwikkelaar de taal kan gebruiken om constructies te maken die geen zin hebben. De compiler ze allemaal laten vangen is gewoon te veel moeite en meestal niet de moeite waard.

Het tweede geval wordt direct aangeroepen in de C#-taalspecificatie aan het begin van sectie 8.0

Het voorbeeld resulteert in een compile-time-fout omdat een if-statement een embedded-statement vereist in plaats van een statement voor zijn if-branch. Als deze code was toegestaan, zou de variabele i worden gedeclareerd, maar deze zou nooit kunnen worden gebruikt. Merk echter op dat door de verklaring van i in een blok te plaatsen, het voorbeeld geldig is.

Voorbeeldcode

void F(bool b) {
    if (b)
        int i = 44;
}

Antwoord 4

Het toevoegen van de accolades voor sluiten en openen aan het else-gedeelte van de if heeft me geholpen zoals ik hieronder heb gedaan, in tegenstelling tot wat ik aan het doen was voordat ik ze toevoeg;

Vroeger:dit veroorzaakte de fout:

protected void btnAdd_Click(object sender, EventArgs e)
    {
        if (btnAdd.Text == "ADD")
        {
            CATEGORY cat = new CATEGORY
            {
                NAME = tbxCategory.Text.Trim(),
                TOTALSALEVALUE = tbxSaleValue.Text.Trim(),
                PROFIT = tbxProfit.Text.Trim()
            };
            dm.AddCategory(cat, tbxCategory.Text.Trim());
        }
        else
        // missing brackets - this was causing the error
            var c = getCategory();
            c.NAME = tbxCategory.Text.Trim();
            c.TOTALSALEVALUE = tbxSaleValue.Text.Trim();
            c.PROFIT = tbxProfit.Text.Trim();
            dm.UpdateCategory(c);
        btnSearchCat_Click(btnSearchCat, e);
    }

Na:haakjes toegevoegd in de else-tak

protected void btnAdd_Click(object sender, EventArgs e)
    {
        if (btnAdd.Text == "ADD")
        {
            CATEGORY cat = new CATEGORY
            {
                NAME = tbxCategory.Text.Trim(),
                TOTALSALEVALUE = tbxSaleValue.Text.Trim(),
                PROFIT = tbxProfit.Text.Trim()
            };
            dm.AddCategory(cat, tbxCategory.Text.Trim());
        }
        else
        {
            var c = getCategory();
            c.NAME = tbxCategory.Text.Trim();
            c.TOTALSALEVALUE = tbxSaleValue.Text.Trim();
            c.PROFIT = tbxProfit.Text.Trim();
            dm.UpdateCategory(c);
        }
        btnSearchCat_Click(btnSearchCat, e);
    }

Other episodes