Abaixo está uma postagem do seguinte artigo :
A diferença entre coerção e fundição é freqüentemente negligenciada. Eu posso ver por quê; muitas linguagens têm a mesma sintaxe (ou similar) e terminologia para ambas as operações. Alguns idiomas podem até mesmo se referir a qualquer conversão como “fundição”, mas a explicação a seguir se refere a conceitos no CTS.
Se estiver tentando atribuir um valor de algum tipo a um local de um tipo diferente, você pode gerar um valor do novo tipo que tenha um significado semelhante ao original. Isso é coerção. A coerção permite usar o novo tipo criando um novo valor que de alguma forma se parece com o original. Algumas coerções podem descartar dados (por exemplo, converter o int 0x12345678 para o short 0x5678), enquanto outras não (por exemplo, converter o int 0x00000008 para o short 0x0008 ou o longo 0x0000000000000008).
Lembre-se de que os valores podem ter vários tipos. Se a sua situação for um pouco diferente e você só quiser selecionar um tipo diferente de valor, a fundição é a ferramenta para o trabalho. A conversão simplesmente indica que você deseja operar em um tipo específico que inclui um valor.
A diferença no nível de código varia de C # a IL. Em C #, tanto o elenco quanto a coerção são bastante semelhantes:
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;
}
No nível IL, eles são bastante diferentes:
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
Quanto ao nível lógico, existem algumas diferenças importantes. O que é mais importante lembrar é que a coerção cria um novo valor, enquanto o casting não. A identidade do valor original e do valor após a conversão são os mesmos, enquanto a identidade de um valor coagido difere do valor original; a coersão cria uma instância nova e distinta, enquanto o elenco não. Um corolário é que o resultado da fundição e o original sempre serão equivalentes (tanto em identidade quanto em igualdade), mas um valor coagido pode ou não ser igual ao original e nunca compartilhar a identidade original.
É fácil ver as implicações da coerção nos exemplos acima, pois os tipos numéricos são sempre copiados por valor. As coisas ficam um pouco mais complicadas quando você está trabalhando com tipos de referência.
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 };
}
}
No exemplo abaixo, uma conversão é um elenco, enquanto a outra é uma coerção.
Tuple<string, string> tuple = name;
string[] strings = name;
Após essas conversões, tupla e nome são iguais, mas strings não são iguais a nenhum deles. Você poderia tornar a situação um pouco melhor (ou um pouco mais confusa) implementando Equals () e operator == () na classe Name para comparar um Name e uma string []. Esses operadores “consertariam” o problema de comparação, mas você ainda teria duas instâncias separadas; qualquer modificação nas strings não seria refletida no nome ou tupla, enquanto as mudanças em nome ou tupla seriam refletidas no nome e na tupla, mas não nas strings.
Embora o exemplo acima tenha como objetivo ilustrar algumas diferenças entre conversão e coerção, ele também serve como um ótimo exemplo de por que você deve ser extremamente cauteloso ao usar operadores de conversão com tipos de referência em C #.