parametro - passaggio parametri per valore o riferimento c#




Qual è il valore di un blocco anonimo non assegnato in C#? (7)

In C # puoi creare un blocco all'interno di un metodo che non è collegato ad altre istruzioni.

    public void TestMethod()
    {
        {
            string x = "test";
            string y = x;

            {
                int z = 42;
                int zz = z;
            }
        }
    }

Questo codice viene compilato ed eseguito proprio come se le parentesi all'interno del metodo principale non fossero presenti. Notare anche il blocco all'interno di un blocco.

C'è uno scenario in cui questo sarebbe utile? Non ne ho ancora trovato, ma sono curioso di sapere delle scoperte di altre persone.


Per quanto posso vedere, sarebbe utile solo da un punto di vista organizzativo. Non riesco davvero a concepire alcun valore logico nel farlo. Forse qualcuno avrà un esempio adeguato.


Un esempio potrebbe essere se si volesse riutilizzare un nome di variabile, normalmente non è possibile riutilizzare i nomi di variabili Questo non è valido

        int a = 10;
        Console.WriteLine(a);

        int a = 20;
        Console.WriteLine(a);

ma questo è:

    {
        int a = 10;
        Console.WriteLine(a);
    }
    {
        int a = 20;
        Console.WriteLine(a);
    }

L'unica cosa che riesco a pensare in questo momento, ad esempio se stavi elaborando un oggetto di grandi dimensioni, e ne estrai alcune informazioni, e dopo che avresti eseguito un sacco di operazioni, potresti mettere l'elaborazione dell'oggetto di grandi dimensioni in un blocco, in modo che vada fuori dal campo di applicazione, quindi continuare con le altre operazioni

    {
        //Process a large object and extract some data
    }
    //large object is out of scope here and will be garbage collected, 
    //you can now perform other operations with the extracted data that can take a long time, 
    //without holding the large object in memory

    //do processing with extracted data

Anche se fosse effettivamente utile per qualsiasi ragione (ad es. Controllo della portata variabile), vorrei scoraggiarvi da tale costrutto dal punto di vista della buona leggibilità del vecchio codice.


Ciò consente di creare un blocco di ambito ovunque. Non è così utile da solo, ma può semplificare la logica:

switch( value )
{
    case const1: 
        int i = GetValueSomeHow();
        //do something
        return i.ToString();

    case const2:
        int i = GetADifferentValue();
        //this will throw an exception - i is already declared
 ...

In C # possiamo usare un blocco di scope in modo che gli articoli dichiarati sotto ogni caso siano solo di ambito in quel caso:

switch( value )
{
    case const1: 
    {
        int i = GetValueSomeHow();
        //do something
        return i.ToString();
    }

    case const2:
    {
        int i = GetADifferentValue();
        //no exception now
        return SomeFunctionOfInt( i );
    }
 ...

Questo può funzionare anche per goto ed etichette, non che tu le usi spesso in C #.


Non vi è alcun valore a questo oltre che semantico e per ambito e garbage collection, nessuno dei quali è significativo in questo esempio limitato. Se pensi che rendi il codice più chiaro, per te stesso e / o per gli altri, allora potresti certamente usarlo. Tuttavia, la convenzione più accettata per il chiarimento semantico nel codice generalmente userebbe le interruzioni di riga solo con i commenti in linea di opzione:

public void TestMethod()
{
    //do something with some strings
    string x = "test";
    string y = x;

    //do something else with some ints
    int z = 42;
    int zz = z;
}

Una ragione per farlo è che le variabili 'z' e 'zz' non sarebbero disponibili per il codice sotto la fine di quel blocco interno. Quando si esegue questa operazione in Java, la JVM inserisce uno stack frame per il codice interno e questi valori possono essere presenti nello stack. Quando il codice esce dal blocco, la cornice dello stack viene spuntata e quei valori scompaiono. A seconda dei tipi coinvolti, questo può evitare di dover utilizzare heap e / o garbage collection.


Ambito e garbage collection: quando lasci il blocco non collegato, tutte le variabili dichiarate al suo interno escono dallo scope. Ciò consente al garbage collector di ripulire quegli oggetti.

Ray Hayes sottolinea che il garbage collector .NET non raccoglierà immediatamente gli oggetti fuori portata, quindi il vantaggio principale è l'ambito.





c#