以下は、次の記事からの投稿です。
強制とキャスティングの違いはしばしば無視されます。理由がわかります。多くの言語では、両方の操作で同じ(または類似の)構文と用語が使用されています。一部の言語では、変換を「キャスト」と呼ぶこともありますが、以下の説明では、CTSの概念について説明します。
あるタイプの値を別のタイプの場所に割り当てようとしている場合は、元のタイプと同様の意味を持つ新しいタイプの値を生成できます。これは強制です。Coercionを使用すると、元の値に何らかの形で似た新しい値を作成することで、新しいタイプを使用できます。一部の強制はデータを破棄する場合があり(たとえば、int 0x12345678を短い0x5678に変換する)、他の強制は破棄しない場合があります(たとえば、int 0x00000008を短い0x0008または長い0x0000000000000008に変換する)。
値には複数のタイプがある可能性があることを思い出してください。状況が少し異なり、値のタイプの1つだけを選択したい場合は、キャストがその仕事のツールです。キャストは、値に含まれる特定のタイプを操作することを単に示します。
コードレベルでの違いは、C#によって異なります。C#では、キャストと強制の両方がかなり似ています。
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;
}
ILレベルでは、それらはまったく異なります。
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
論理レベルに関しては、いくつかの重要な違いがあります。覚えておくべき最も重要なことは、強制は新しい価値を生み出すが、キャストはそうではないということです。元の値のIDとキャスト後の値は同じですが、強制された値のIDは元の値とは異なります。強制は新しい別個のインスタンスを作成しますが、キャストは作成しません。当然の結果として、キャストの結果とオリジナルは常に同等になります(同一性と同等性の両方)が、強制された値はオリジナルと等しい場合と等しくない場合があり、元のアイデンティティを共有することはありません。
数値型は常に値によってコピーされるため、上記の例では強制の影響を簡単に確認できます。参照型を操作しているときは、少し注意が必要です。
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 };
}
}
以下の例では、一方の変換はキャストであり、もう一方は強制です。
Tuple<string, string> tuple = name;
string[] strings = name;
これらの変換後、タプルと名前は等しくなりますが、文字列はどちらとも等しくなりません。NameクラスにEquals()と演算子==()を実装して、Nameとstring []を比較することで、状況を少し良く(または少し混乱させて)することができます。これらの演算子は比較の問題を「修正」しますが、それでも2つの別々のインスタンスがあります。文字列への変更は名前またはタプルに反映されませんが、名前またはタプルのいずれかへの変更は名前とタプルに反映されますが、文字列には反映されません。
上記の例は、キャストと強制の違いを説明することを目的としていますが、C#で参照型を使用して変換演算子を使用する場合に非常に注意する必要がある理由の優れた例としても役立ちます。