Unten ist ein Beitrag aus dem folgenden Artikel :
Der Unterschied zwischen Zwang und Gießen wird oft vernachlässigt. Ich kann sehen warum; Viele Sprachen haben für beide Operationen dieselbe (oder eine ähnliche) Syntax und Terminologie. Einige Sprachen bezeichnen eine Konvertierung möglicherweise sogar als "Casting". Die folgende Erklärung bezieht sich jedoch auf Konzepte im CTS.
Wenn Sie versuchen, einem Speicherort eines anderen Typs einen Wert eines bestimmten Typs zuzuweisen, können Sie einen Wert des neuen Typs generieren, der eine ähnliche Bedeutung wie das Original hat. Das ist Zwang. Mit Zwang können Sie den neuen Typ verwenden, indem Sie einen neuen Wert erstellen, der in gewisser Weise dem Original ähnelt. Einige Zwänge verwerfen möglicherweise Daten (z. B. Konvertieren des int 0x12345678 in den kurzen 0x5678), andere möglicherweise nicht (z. B. Konvertieren des int 0x00000008 in den kurzen 0x0008 oder des langen 0x0000000000000008).
Denken Sie daran, dass Werte mehrere Typen haben können. Wenn Ihre Situation etwas anders ist und Sie nur einen anderen Werttyp auswählen möchten, ist das Casting das Werkzeug für den Job. Das Casting zeigt lediglich an, dass Sie einen bestimmten Typ bearbeiten möchten, den ein Wert enthält.
Der Unterschied auf Codeebene variiert von C # bis IL. In C # sehen Casting und Zwang ziemlich ähnlich aus:
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;
}
Auf IL-Ebene sind sie ganz anders:
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
In Bezug auf die logische Ebene gibt es einige wichtige Unterschiede. Was am wichtigsten ist, ist, dass Zwang einen neuen Wert schafft, Casting jedoch nicht. Die Identität des ursprünglichen Werts und der Wert nach dem Gießen sind gleich, während sich die Identität eines erzwungenen Werts vom ursprünglichen Wert unterscheidet. Durch das Zusammenwirken wird eine neue, eindeutige Instanz erstellt, durch das Casting jedoch nicht. Eine Konsequenz ist, dass das Ergebnis des Castings und des Originals immer gleichwertig sind (sowohl in Bezug auf Identität als auch in Bezug auf Gleichheit), aber ein erzwungener Wert kann gleich oder nicht gleich dem Original sein und niemals die ursprüngliche Identität teilen.
Die Auswirkungen von Zwang sind in den obigen Beispielen leicht zu erkennen, da die numerischen Typen immer nach Wert kopiert werden. Bei der Arbeit mit Referenztypen wird es etwas schwieriger.
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 };
}
}
Im folgenden Beispiel ist eine Konvertierung eine Besetzung, während die andere ein Zwang ist.
Tuple<string, string> tuple = name;
string[] strings = name;
Nach diesen Konvertierungen sind Tupel und Name gleich, aber Zeichenfolgen sind nicht gleich. Sie könnten die Situation etwas verbessern (oder etwas verwirrender), indem Sie Equals () und operator == () in der Name-Klasse implementieren, um einen Namen und eine Zeichenfolge [] zu vergleichen. Diese Operatoren würden das Vergleichsproblem "beheben", aber Sie hätten immer noch zwei separate Instanzen. Änderungen an Zeichenfolgen werden nicht in Namen oder Tupeln wiedergegeben, während Änderungen an Namen oder Tupeln in Namen und Tupel wiedergegeben werden, jedoch nicht in Zeichenfolgen.
Obwohl das obige Beispiel einige Unterschiede zwischen Gießen und Zwang veranschaulichen sollte, dient es auch als gutes Beispiel dafür, warum Sie bei der Verwendung von Konvertierungsoperatoren mit Referenztypen in C # äußerst vorsichtig sein sollten.