I delegati di C # sono immutabili - ma perché importa?

8

Questa è una domanda successiva a questa altra domanda.

Sfondo

Lavorando dal tutorial sui delegati MSDN (C #) , Vedo il seguente:

Note that once a delegate is created, the method it is associated with never changes — delegate objects are immutable.

E poi, nel codice di esempio, vedo questo (Spiega un po 'il codice):

public delegate void ProcessBookDelegate(Book book);

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));

La domanda

Ora ovviamente, il modo in cui il codice è scritto qui crea un nuovo delegato per ciascuno processi. Sto indovinando che l'immutabilità è pertinente se provi a fare cose del tipo

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);
ProcessBookDelegate thisIsATest = new ProcessBookDelegate(totaller.AddBookToTotal);

che dovrebbe ... essere ancora compilato quando thisIsATest è immutabile? Quindi, quale problema ha risolto Microsoft rendendolo immutabile? Quali problemi dovremmo incontrare se C # 6 rendesse mutabili i delegati?

Modifica

Credo che l'immutabilità impedirà questo:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);

thisIsATest.ChangeTheDelegateInABadFashion();

someFunction(thisIsATest); //This function works as normal
                           //because the delegate is unchanged
                           //due to immutability

ma l'immutabilità NON lo impedirà:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);

thisIsATest = new ProcessBookDelegate(ChangeTheDelegateInABadFashion());

someFunction(thisIsATest); //This function works weird now because
                           //it expected the unchanged delegate

Sono corretto in questa comprensione?

    
posta medivh 13.09.2013 - 09:44
fonte

4 risposte

15

Penso che tu stia mescolando ciò che significa immutabilità.

Che immutabilità non è

Dai un'occhiata a questo esempio:

string s = "Hello";
s = "World";

Sono string s immutabili? Sì.
Questo verrà compilato? Sì.
Abbiamo in qualche modo modificato l'istanza della stringa? No .

Non apportiamo alcuna modifica a "Hello" . Stiamo creando una stringa, assegnandola alla variabile s , quindi stiamo creando un nuovo string e sovrascrivendo la variabile s con questo nuovo string . L'immutabilità non ha un ruolo qui.

Che cos'è l'immutabilità

Se dovessimo provare qualcosa del genere:

s.MutateInSomeWay();

dove MutateInSomeWay è un metodo che modifica la stringa "Hello" (il valore di s ) stesso, che non sarebbe valido a causa dell'immutabilità della stringa.

Qualsiasi metodo di string che lo modifica in qualche modo non lo modifica, ma crea un nuovo string con il valore modificato e lo restituisce al chiamante.

but the immutability will NOT prevent this:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);  
thisIsATest = new ProcessBookDelegate(ChangeTheDelegateInABadFashion());
someFunction(thisIsATest); //This function works weird now because
//it expected the unchanged delegate

Am I correct in this understanding?

Sì, l'immutabilità non la impedirà perché è perfettamente valida, non hai mutato alcun oggetto. Ovviamente, non sei del tutto chiaro su cosa sia ChangeTheDelegateInABadFashion() , quindi è difficile essere specifici.

    
risposta data 13.09.2013 - 13:08
fonte
4

Ragioni in breve:

  • Un oggetto immutabile può trovarsi esattamente in uno stato, lo stato in cui è stato creato (sicurezza)
  • I thread-safe possono essere utilizzati liberamente
  • Ottimizzazione memoria
  • Le prestazioni sono migliori

Dai un'occhiata a queste due domande su Stack Overflow per maggiori informazioni:

risposta data 13.09.2013 - 11:34
fonte
2

credo che la sicurezza dei thread standard; se sai che un delegato non cambierà mai, puoi fare alcune ipotesi al riguardo

in particolare, puoi essere certo che un codice malvagio non può cambiare il delegato che stai passando a diverse funzioni (anche accidentalmente)

questo potrebbe causare bug difficili da rintracciare e lasciare che il programmatore si chieda perché il suo delegato non sia stato chiamato

    
risposta data 13.09.2013 - 10:01
fonte
2

La semplice risposta sta mutando un delegato ha molto poco senso. Un delegato è molto un riferimento a una funzione, un insieme di codice in esecuzione. Mutare ciò suggerisce che stai mutando quella funzione.

Chiedi a te stesso, come sarebbe il metodo su un delegato e cosa farebbe? In un certo senso, riscriverebbe il codice di quella funzione. Ciò apre una quantità enorme (quasi intrattabile) di complessità alle specifiche C # e alle implementazioni del compilatore per un beneficio minimo con costi di prestazioni elevati. Da qui la restrizione.

    
risposta data 14.09.2013 - 01:14
fonte

Leggi altre domande sui tag