[c#] Tipo di riferimento stringa C #?


3 Answers

Se dobbiamo rispondere alla domanda: String è un tipo di riferimento e si comporta come un riferimento. Passiamo un parametro che contiene un riferimento a, non la stringa effettiva. Il problema è nella funzione:

public static void TestI(string test)
{
    test = "after passing";
}

Il test parametri contiene un riferimento alla stringa ma è una copia. Abbiamo due variabili che puntano alla stringa. E poiché ogni operazione con le stringhe crea effettivamente un nuovo oggetto, facciamo in modo che la nostra copia locale faccia riferimento alla nuova stringa. Ma la variabile di test originale non è cambiata.

Le soluzioni suggerite per mettere ref nella dichiarazione di funzione e nell'invocazione funzionano perché non passeremo il valore della variabile di test ma passeremo solo un riferimento ad esso. Pertanto qualsiasi modifica all'interno della funzione rifletterà la variabile originale.

Voglio ripetere alla fine: String è un tipo di riferimento ma dal momento che è immutabile la riga test = "after passing"; crea effettivamente un nuovo oggetto e la copia esterna della variabile test viene cambiata in modo che punti alla nuova stringa.

Question

So che "string" in C # è un tipo di riferimento. Questo è su MSDN. Tuttavia, questo codice non funziona come dovrebbe allora:

class Test
{
    public static void Main()
    {
        string test = "before passing";
        Console.WriteLine(test);
        TestI(test);
        Console.WriteLine(test);
    }

    public static void TestI(string test)
    {
        test = "after passing";
    }
}

L'output dovrebbe essere "prima di passare" "dopo aver superato" poiché sto passando la stringa come parametro e trattandosi di un tipo di riferimento, la seconda istruzione di output dovrebbe riconoscere che il testo è cambiato nel metodo TestI. Tuttavia, ottengo "prima di passare" "prima di passare", facendo sembrare che sia passato per valore non da ref. Capisco che le stringhe siano immutabili, ma non vedo come ciò spiegherebbe cosa sta succedendo qui. Cosa mi manca? Grazie.




Le risposte sopra sono utili, vorrei solo aggiungere un esempio che penso dimostri chiaramente cosa succede quando passiamo il parametro senza la parola chiave ref, anche quando quel parametro è un tipo di riferimento:

MyClass c = new MyClass(); c.MyProperty = "foo";

CNull(c); // only a copy of the reference is sent 
Console.WriteLine(c.MyProperty); // still foo, we only made the copy null
CPropertyChange(c); 
Console.WriteLine(c.MyProperty); // bar


private void CNull(MyClass c2)
        {          
            c2 = null;
        }
private void CPropertyChange(MyClass c2) 
        {
            c2.MyProperty = "bar"; // c2 is a copy, but it refers to the same object that c does (on heap) and modified property would appear on c.MyProperty as well.
        }



In realtà sarebbe stato lo stesso per qualsiasi oggetto, per esempio essere un tipo di riferimento e passare per riferimento sono 2 cose diverse in c #.

Questo funzionerebbe, ma ciò vale indipendentemente dal tipo:

public static void TestI(ref string test)

Anche riguardo alla stringa come tipo di riferimento, è anche speciale. È progettato per essere immutabile, quindi tutti i suoi metodi non modificheranno l'istanza (ne restituiscono una nuova). Ha anche alcune cose extra in esso per le prestazioni.




Credo che il tuo codice sia analogo al seguente e non dovresti aspettarti che il valore sia cambiato per lo stesso motivo per cui non sarebbe stato qui:

 public static void Main()
 {
     StringWrapper testVariable = new StringWrapper("before passing");
     Console.WriteLine(testVariable);
     TestI(testVariable);
     Console.WriteLine(testVariable);
 }

 public static void TestI(StringWrapper testParameter)
 {
     testParameter = new StringWrapper("after passing");

     // this will change the object that testParameter is pointing/referring
     // to but it doesn't change testVariable unless you use a reference
     // parameter as indicated in other answers
 }





Related