Di seguito è riportato un messaggio dal seguente articolo :
La differenza tra coercizione e casting è spesso trascurata. Posso capire perché; molte lingue hanno la stessa (o simile) sintassi e terminologia per entrambe le operazioni. Alcune lingue possono anche riferirsi a qualsiasi conversione come "casting", ma la seguente spiegazione si riferisce ai concetti nel CTS.
Se stai cercando di assegnare un valore di un tipo a una posizione di un tipo diverso, puoi generare un valore del nuovo tipo che ha un significato simile all'originale. Questa è coercizione. La coercizione ti consente di utilizzare il nuovo tipo creando un nuovo valore che in qualche modo assomigli all'originale. Alcune coercizioni possono scartare i dati (ad esempio convertendo l'int 0x12345678 nello short 0x5678), mentre altre no (ad esempio convertendo l'int 0x00000008 nello short 0x0008, o il lungo 0x0000000000000008).
Ricorda che i valori possono avere più tipi. Se la tua situazione è leggermente diversa e desideri selezionare solo uno diverso dei tipi di valore, il casting è lo strumento per il lavoro. Il casting indica semplicemente che desideri operare su un tipo particolare incluso in un valore.
La differenza a livello di codice varia da C # a IL. In C #, sia il casting che la coercizione sono abbastanza simili:
static void ChangeTypes(int number, System.IO.Stream stream)
{
long longNumber = number;
short shortNumber = (short)number;
IDisposable disposableStream = stream;
System.IO.FileStream fileStream = (System.IO.FileStream)stream;
}
A livello IL sono abbastanza diversi:
ldarg.0
conv.i8
stloc.0
ldarg.0
conv.i2
stloc.1
ldarg.1
stloc.2
ldarg.1
castclass [mscorlib]System.IO.FileStream
stloc.3
Per quanto riguarda il livello logico, ci sono alcune importanti differenze. La cosa più importante da ricordare è che la coercizione crea un nuovo valore, mentre il casting no. L'identità del valore originale e il valore dopo la fusione sono gli stessi, mentre l'identità di un valore coatto differisce dal valore originale; la coersione crea una nuova istanza distinta, mentre il casting no. Un corollario è che il risultato del casting e l'originale saranno sempre equivalenti (sia nell'identità che nell'uguaglianza), ma un valore coercitivo può o non può essere uguale all'originale e non condivide mai l'identità originale.
È facile vedere le implicazioni della coercizione negli esempi precedenti, poiché i tipi numerici vengono sempre copiati per valore. Le cose diventano un po 'più complicate quando lavori con i tipi di riferimento.
class Name : Tuple<string, string>
{
public Name(string first, string last)
: base(first, last)
{
}
public static implicit operator string[](Name name)
{
return new string[] { name.Item1, name.Item2 };
}
}
Nell'esempio seguente, una conversione è un cast, mentre l'altra è una coercizione.
Tuple<string, string> tuple = name;
string[] strings = name;
Dopo queste conversioni, tupla e nome sono uguali, ma le stringhe non sono uguali a nessuna delle due. Si potrebbe rendere la situazione leggermente migliore (o leggermente più confusa) implementando Equals () e l'operatore == () sulla classe Name per confrontare un nome e una stringa []. Questi operatori avrebbero "risolto" il problema di confronto, ma avresti comunque due istanze separate; qualsiasi modifica alle stringhe non si rifletterà nel nome o nella tupla, mentre le modifiche a una di nome o alla tupla si rifletteranno in nome e tupla, ma non nelle stringhe.
Sebbene l'esempio precedente avesse lo scopo di illustrare alcune differenze tra casting e coercizione, serve anche come un ottimo esempio del motivo per cui dovresti essere estremamente cauto nell'usare operatori di conversione con tipi di riferimento in C #.