어떻게 든 동등하다고 볼 수 있더라도 목적이 완전히 다릅니다. 먼저 캐스트가 무엇인지 정의 해 보겠습니다.
캐스팅은 한 데이터 유형의 엔티티를 다른 유형으로 변경하는 작업입니다.
캐스트는 종종 동일한 변환 구문을 갖기 때문에 약간 일반적이며 변환 과 동일합니다. 그러므로 질문은 언어에서 캐스트 (암시 적 또는 명시 적)를 허용 할 때와 언제 ( 더) 명시 적 변환?
먼저 그들 사이에 간단한 선을 그리 겠습니다 . 형식적으로 (언어 구문과 동일하더라도) 캐스트는 유형을 변경하는 반면 변환은 값을 변경하거나 변경할 수 있습니다 (결국 함께 유형 함께). 또한 캐스트는 되돌릴 수 있지만 변환은 불가능할 수 있습니다.
이 주제는 상당히 방대하므로 게임에서 커스텀 캐스트 연산자를 제외하여 조금 좁혀 보겠습니다.
암시 적 캐스트
C #에서는 정보를 잃지 않을 때 캐스트가 암시 적 입니다 (이 검사는 실제 값이 아닌 형식 으로 수행 됩니다. ).
기본 유형
예를 들면 :
int tinyInteger = 10;
long bigInteger = tinyInteger;
float tinyReal = 10.0f;
double bigReal = tinyReal;
이러한 캐스트는 변환하는 동안 정보를 잃지 않을 것이기 때문에 암시 적입니다 (유형을 더 넓게 만들기 만하면 됨). 그 반대의 경우 암시 적 캐스트는 허용되지 않습니다. 실제 값에 관계없이 (런타임에서만 확인할 수 있기 때문에) 변환 중에 일부 정보가 손실 될 수 있기 때문입니다. 예를 들어이 코드는 다음 double과 같이 표현할 수없는 값을 포함 할 수 있기 때문에 컴파일 되지 않습니다 float.
double bigReal = Double.MaxValue;
float tinyReal = bigReal;
사물
객체 (에 대한 포인터)의 경우 컴파일러가 소스 유형이 파생 클래스 (또는 대상 클래스의 유형을 구현)인지 확인할 수있을 때 캐스트는 항상 암시 적입니다. 예를 들면 다음과 같습니다.
string text = "123";
IFormattable formattable = text;
NotSupportedException derivedException = new NotSupportedException();
Exception baseException = derivedException;
이 경우 컴파일러는 알고 그 string구현을 IFormattable하고는 NotSupportedException(에서 파생)입니다 Exception캐스트가 암시하므로. 객체가 유형을 변경하지 않기 때문에 정보가 손실되지 않습니다 ( struct캐스트를 사용하면 다른 유형 의 새 객체 를 생성하기 때문에 s 및 기본 유형과 다릅니다 ). 뷰 가 변경됩니다. 그들.
명시 적 캐스트
변환이 컴파일러에 의해 암시 적으로 수행되지 않은 경우 캐스트는 명시 적이며 캐스트 연산자를 사용해야합니다. 일반적으로 다음을 의미합니다.
- 정보 나 데이터를 잃을 수 있으므로 알고 있어야합니다.
- 변환이 실패 할 수 있습니다 (한 유형을 다른 유형으로 변환 할 수 없기 때문에). 따라서 수행중인 작업을 알고 있어야합니다.
기본 유형
변환 중에 일부 데이터가 손실 될 수있는 경우 기본 유형에 대해 명시 적 캐스트가 필요합니다. 예를 들면 다음과 같습니다.
double precise = Math.Cos(Math.PI * 1.23456) / Math.Sin(1.23456);
float coarse = (float)precise;
float epsilon = (float)Double.Epsilon;
두 예에서 값이 float범위 내에 있더라도 정보 (이 경우 정밀도)가 손실되므로 변환이 명시 적이어야합니다. 이제 이것을 시도하십시오.
float max = (float)Double.MaxValue;
이 변환은 실패하므로 다시 명시 적이어야하며이를인지하고 확인을 수행 할 수 있습니다 (이 예에서는 값이 일정하지만 일부 런타임 계산 또는 I / O에서 올 수 있음). 귀하의 예로 돌아가십시오.
string text = "123";
double value = (double)text;
컴파일러가 텍스트를 숫자로 변환 할 수 없기 때문에 컴파일되지 않습니다. 텍스트에는 숫자뿐만 아니라 모든 문자가 포함될 수 있으며 C #에서는 명시 적 캐스트의 경우에도 너무 많습니다 (하지만 다른 언어에서는 허용 될 수 있음).
사물
유형이 관련되지 않은 경우 포인터에서 객체로의 변환이 실패 할 수 있습니다. 예를 들어이 코드는 컴파일되지 않습니다 (컴파일러가 가능한 변환이 없음을 알고 있기 때문).
string text = (string)AppDomain.Current;
Exception exception = (Exception)"abc";
이 코드는 컴파일되지만 런타임에 실패 할 수 있습니다 (캐스트 된 객체의 유효 유형에 따라 다름) InvalidCastException.
object obj = GetNextObjectFromInput();
string text = (string)obj;
obj = GetNextObjectFromInput();
Exception exception = (Exception)obj;
전환
그래서 마지막으로 캐스트가 변환이라면 왜 우리는 같은 클래스가 필요 Convert합니까? 실제로 Convert구현 및 IConvertible구현 에서 발생하는 미묘한 차이점을 무시하는 것은 C #에서 캐스트를 사용하여 컴파일러에 말하기 때문입니다.
저를 믿으세요.이 타입은 지금은 알 수 없더라도 저런 타입입니다.
-또는-
걱정하지 마세요.이 전환에서 무언가가 손실 되더라도 상관 없습니다.
다른 어떤 경우에는 보다 명시적인 작업이 필요합니다 ( 쉬운 캐스트의 의미에 대해 생각해보십시오. 이것이 C ++에서 길고 장황하며 명시적인 구문을 도입 한 이유입니다). 이것은 복잡한 작업을 포함 할 수 있습니다 ( string-> double변환을 위해 구문 분석이 필요합니다). string예를 들어으로 변환하는 것은 항상 가능합니다 ( ToString()메소드 를 통해 ).하지만 예상과 다른 것을 의미 할 수 있으므로 캐스트보다 더 명시 적이어야합니다 ( 더 많이 작성하고 수행중인 작업에 대해 더 많이 생각합니다. ).
이 변환은 사용자 지정 변환 연산자 (캐스트 할 클래스에 정의 됨) 또는 더 복잡한 메커니즘 ( TypeConverter예 : s 또는 클래스 메서드 )을 사용하여 객체 내에서 수행 할 수 있습니다 (알려진 IL 명령어 사용 ). 어떤 일이 일어날 지 모르지만 실패 할 수 있다는 것을 알고 있습니다 (더 제어 된 변환이 가능할 때 IMO 를 사용해야하는 이유입니다). 귀하의 경우 변환은 단순히을 구문 분석하여 다음 string을 생성합니다 double.
double value = Double.Parse(aStringVariable);
물론 이것은 실패 할 수 있으므로이를 수행하면 항상 예외가 발생할 수 있습니다 ( FormatException). 그것은 여기에 주제에 밖으로이다 그러나이 때 TryParse사용할 수 있습니다 의미 당신이 때문에 당신은 (그것을 사용한다 라고 는 숫자하지 않을 수 있습니다 그것은 실패 ...도 빠릅니다).
.NET의 변환은 TypeConverter사용자 정의 변환 연산자를 사용한 암시 적 / 명시 적 캐스트,IConvertible 메서드 및 구문 분석 (내가 잊은 것이 있습니까?) . 이에 대한 자세한 내용은 MSDN을 참조하십시오.
이 긴 대답을 끝내려면 사용자 정의 변환 연산자에 대해 몇 마디 만하면됩니다. 그것은 단지 설탕 프로그래머가 다른 한 가지 유형으로 캐스팅을 사용하게 할 수 있습니다. "이 유형을 해당 유형으로 변환하려면 내가 할 수 있습니다"라고 말하는 클래스 (캐스트 될 것) 내부의 메소드입니다. 예를 들면 :
float? maybe = 10;
float sure1 = (float)maybe;
float sure2 = maybe.Value;
이 경우 실패 할 수 있기 때문에 명시 적이지만 구현에 맡겨집니다 (이에 대한 지침이 있더라도). 다음과 같은 사용자 지정 문자열 클래스를 작성한다고 가정 해보십시오.
EasyString text = "123";
double value = (string)text;
구현에서 "프로그래머의 삶을 더 쉽게 만들기"를 결정하고 캐스트를 통해이 변환을 노출 할 수 있습니다 (단순히 작성하는 지름길 일뿐임을 기억하십시오). 일부 언어는이를 허용 할 수도 있습니다.
double value = "123";
모든 유형에 대한 암시 적 변환 허용 (확인은 런타임에 수행됨). 적절한 옵션을 사용하면 예를 들어 VB.NET에서이를 수행 할 수 있습니다. 그것은 단지 다른 철학입니다.
그들로 무엇을 할 수 있습니까?
그래서 마지막 질문은 언제 하나 또는 다른 것을 사용해야 하는가입니다. 언제 명시 적 캐스트를 사용할 수 있는지 살펴 보겠습니다.
- 기본 유형 간의 변환.
- 전환
object 다른 유형으로의 (개봉도 포함될 수 있음).
- 파생 클래스에서 기본 클래스 (또는 구현 된 인터페이스) 로의 변환.
- 사용자 지정 변환 연산자를 통해 한 유형에서 다른 유형으로 변환합니다.
첫 번째 변환 만 수행 할 수 있습니다. Convert 선택의 여지가없고 명시 적 캐스트를 사용해야합니다.
이제 언제 사용할 수 있는지 보겠습니다 Convert.
- 모든 기본 유형에서 다른 기본 유형으로의 변환 (몇 가지 제한 사항이 있음, MSDN 참조 ).
IConvertible다른 (지원되는) 유형으로 구현되는 모든 유형에서 변환 .
byte배열에서 문자열로 /에서 변환 .
결론
Convert변환이 실패 할 수 있다는 것을 알 때마다 IMO를 사용해야합니다 (형식, 범위 또는 지원되지 않을 수 있기 때문). 캐스트로 동일한 변환을 수행 할 수 있더라도 (다른 것을 사용할 수없는 경우). 누가 여러분의 코드를 읽을 것인지 명확하게 , 그리고 그것이 실패 할 수 있다는 것을 분명히합니다 (디버그 단순화).
캐스트를 사용해야하는 다른 모든 경우에는 선택의 여지가 없지만 다른 더 나은 방법을 사용할 수 있으면 사용하는 것이 좋습니다. 당신의 예에서의 변환 string에는 double가능한 한 (또한 당신이 그것을보다 효율적으로 제어를 얻을 수) 명시 적으로 많이 그것을해야하므로 매우 자주 사용 예를 들어, 실패합니다 (텍스트가 사용자로부터 온다 특히)하는 것이 뭔가 TryParse방법을.
편집 : 그들 사이의 차이점은 무엇입니까?
(대한 업데이트 된 질문에 따라 그리고 내가 전에 쓴 유지 하면 당신은 / 사용 할 수 있습니다 때에 비해 캐스트를 사용할 수 있습니다 Convert또한 (그들 사이의 차이가있는 경우입니다 명확히 다음 마지막 점) Convert용도 IConvertible및 IFormattable인터페이스가 작업을 수행 할 수 있도록 캐스트와 함께 허용되지 않음).
짧은 대답은 그렇습니다. 그들은 다르게 행동합니다 . 나는 Convert클래스가 도우미 메서드 클래스처럼 보이지만 종종 약간의 이점 이나 약간 다른 동작을 제공합니다. 예를 들면 :
double real = 1.6;
int castedInteger = (int)real;
int convertedInteger = Convert.ToInt32(real);
꽤 다르죠? 캐스트는 잘리지 만 (우리 모두가 기대하는 것입니다) Convert가장 가까운 정수로 반올림을 수행합니다 (알지 못하는 경우 예상되지 않을 수 있음). 각 변환 방법에는 차이가 있으므로 일반적인 규칙을 적용 할 수 없으며 사례별로 확인해야합니다 ... 19 가지 기본 유형을 다른 모든 유형으로 변환 할 수 있습니다 ... 목록은 꽤 길 수 있습니다. MSDN 사례를 참조하는 것이 훨씬 좋습니다. 케이스!