Domanda

Faccio ampio uso di ereditarietà, polimorfismo e incapsulamento, ma mi sono appena reso conto che non conoscevo il seguente comportamento sull'ambito di un oggetto rispetto a una variabile. La differenza si mostra meglio con il codice:

public class Obj
{
    public string sss {get; set;}

    public Obj()
    {
        sss = "0";
    } 
}     

public partial class testScope : System.Web.UI.Page
 {
    protected void Page_Load(object sender, EventArgs e)
    { 
        Obj a = new Obj(); 
        String sss = "0";            
        Context.Response.Write(sss); // 0

        FlipString(sss);
        FlipString(a.sss);
        Context.Response.Write(sss + a.sss); // 0 0

        FlipObject(a);
        Context.Response.Write(a.sss); // 1
        Context.Response.End();
    }

    public void FlipString(string str)
    { str = "1"; }

    public void FlipObject(Obj str)
    { str.sss = "1"; }
}

Quindi ho pensato che quando una variabile viene passata in un metodo, le modifiche si limitano all'ambito del metodo. Ma sembra che se un oggetto viene passato in un metodo che cambia nelle sue proprietà si estende oltre il metodo.

Potrei accettarlo se la regola fosse che questo comportamento esiste per l'oggetto e non per le variabili ma in .net tutto è un oggetto, una stringa (come quella nell'esempio è System.String) Quindi qual è la regola, come può prevedo l'ambito di un parametro che passo in un metodo?

È stato utile?

Soluzione

Non si passa mai un oggetto come argomento - si passa sempre solo un riferimento o un valore di tipo valore. A meno che non si usi la parola chiave ref , gli argomenti vengono passati per valore, ovvero il valore iniziale del parametro è il valore valutato dell'argomento e le modifiche al valore del parametro non vengono visualizzate dal chiamante .

Tuttavia, è molto importante capire che il valore del parametro (per un tipo di riferimento) è solo il riferimento . Se si modifica il contenuto dell'oggetto a cui fa riferimento il riferimento, quel cambia verrà visto dal chiamante.

È un argomento che merita più di alcuni paragrafi - ti suggerisco di leggere il mio articolo sul parametro passando in .NET per ulteriori informazioni.

Altri suggerimenti

Penso che ho appena capito google in giro, alcune cose in .net sono " valore " tipi e altri sono "riferimento" tipi, quindi per i tipi di valore il valore viene duplicato quando viene eseguito il marshalling in un metodo, ma i tipi di riferimento hanno un puntatore simile o il riferimento viene passato al metodo che ovviamente condivide lo stesso ambito del genitore. Quindi la mia domanda è come posso sapere se qualcosa è un tipo di valore o no, vedo che le strutture come ints sono tutti tipi di valore ma le stringhe sembrano comportarsi come strutture anche se sono oggetti System.String?

Una classe (Obj nel tuo caso) è un tipo di riferimento , quindi quando chiami la funzione quello che stai realmente facendo è passare un riferimento (puoi fondamentalmente pensarlo come un puntatore sicuro) a questo oggetto. Se si desidera impedire le modifiche agli oggetti mutabili (ad esempio classe / tipi di riferimento), è necessario clonare questo oggetto prima di passarlo alla funzione appropriata (o semplicemente considerare di renderlo una struttura in modo che venga copiato dal valore).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top