아래는 다음 기사 의 게시물입니다 .
강제와 캐스팅의 차이는 종종 무시됩니다. 이유를 알 수 있습니다. 많은 언어가 두 작업에 대해 동일한 (또는 유사한) 구문과 용어를 사용합니다. 일부 언어는 모든 변환을 '캐스트'라고도 할 수 있지만 다음 설명은 CTS의 개념을 참조합니다.
특정 유형의 값을 다른 유형의 위치에 할당하려는 경우 원본과 유사한 의미를 가진 새 유형의 값을 생성 할 수 있습니다. 이것은 강압입니다. 강제 변환을 사용하면 어떤 방식 으로든 원본과 유사한 새 값을 생성하여 새 유형을 사용할 수 있습니다. 일부 강제 변환은 데이터를 버릴 수 있지만 (예 : int 0x12345678을 짧은 0x5678로 변환) 다른 변환은 데이터를 버릴 수 있지만 (예 : int 0x00000008을 짧은 0x0008 또는 긴 0x0000000000000008로 변환).
값은 여러 유형을 가질 수 있습니다. 상황이 약간 다르고 값 유형 중 다른 유형 만 선택하려는 경우 캐스팅이 작업 도구입니다. 캐스트는 단순히 값에 포함 된 특정 유형에 대해 작업하고자 함을 나타냅니다.
코드 수준의 차이는 C #에서 IL에 따라 다릅니다. 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 클래스에서 Name과 string []을 비교하기 위해 Equals () 및 operator == ()를 구현하여 상황을 약간 개선하거나 약간 더 혼란스럽게 만들 수 있습니다. 이러한 연산자는 비교 문제를 "수정"하지만 여전히 두 개의 개별 인스턴스가 있습니다. 문자열에 대한 수정 사항은 이름이나 튜플에 반영되지 않고 이름이나 튜플 중 하나에 대한 변경 사항은 이름과 튜플에 반영되지만 문자열에는 반영되지 않습니다.
위의 예제는 캐스팅과 강제 변환 간의 몇 가지 차이점을 설명하기위한 것이지만 C #에서 참조 형식과 함께 변환 연산자를 사용하는 데 매우주의해야하는 이유를 보여주는 좋은 예이기도합니다.