2010-05-06 5 views
3

업 캐스팅이나 다운 캐스트를 할 때 실제로 장면 뒤에서 어떤 일이 발생합니까? 마지막 줄의 캐스팅으로 유일한 목적은 우리가 잘못된 작업을 수행하지 않는 안전 컴파일러에게 것실제로 CLR 레벨에서 주물이 어떻게 작동합니까?

string myString = "abc"; 
object myObject = myString; 
string myStringBack = (string)myObject; 

: 나는 같은 일을 할 때하는 생각을했다. 따라서 실제로 코드에 캐스팅 코드가 포함되지 않는다는 생각이 들었습니다. 내가 틀렸어 보인다 :

.maxstack 1 
.locals init (
    [0] string myString, 
    [1] object myObject, 
    [2] string myStringBack) 
L_0000: nop 
L_0001: ldstr "abc" 
L_0006: stloc.0 
L_0007: ldloc.0 
L_0008: stloc.1 
L_0009: ldloc.1 
L_000a: castclass string 
L_000f: stloc.2 
L_0010: ret 

왜 CLR은 castclass string과 같은 것이 필요합니까?

풀이 죽은 두 가지 가능한 구현이 있습니다

  1. 당신은 castclass something을 필요가. castclass을 수행하는 코드 줄에 도달하면 CLR은 형 변환을 시도합니다. 그렇다면 캐스트 클래스 문자열을 생략하고 코드를 실행하려고하면 어떻게 될까요?
  2. castclass은 필요하지 않습니다. 모든 참조 유형은 비슷한 내부 구조를 가지므로 Form 인스턴스에서 문자열을 사용하려고하면 양식이 문자열이나 그 부속 유형이 아니므로 잘못된 사용 예외가 발생합니다.

또한 C# 4.0의 다음 statamente는 간단히 요약 할 수 있습니까?

Upcasting and downcasting between compatible reference types performs reference 
conversions: a new reference is created that points to the same object. 

정말 새로운 참조를 만드나요? 나는 그것이 다른 변수 유형에만 저장되는 동일한 참조 일 것이라고 생각했다.

감사

답변

11

실제로 캐스팅 코드는 코드 자체에 임베딩 될 수 없다는 아이디어가있었습니다.

흥미로운 아이디어입니다. 어떻게 이것이 효과가 있다고 상상 했습니까?

try 
{ 
    object x = 123; 
    object y = (string)x; 
} 
catch(InvalidCastException ex) 
{ ... } 

캐스트가 다음 을 더 코드를 생성하지 않는 경우 어디에 않는 예외가 일이 발생 코드? 런타임 유형 검사을 수행 할 수

기억

, 더 구체적인 유형 덜 특정 유형에서 주조의 주된 목적이다.

유형 검사가 통과되면 확실하게 다른 일은 발생하지 않습니다. 타입 체크 전의 레퍼런스 비트와 타입 체크 후의 비트는 같은 비트이다. 우리는 단지 런타임이 이전 비트의 새로운 사용이 정당하다는 것을 검증하도록했습니다.

Form 인스턴스에서 문자열을 사용하려고하면 형식이 문자열이나 그 부속 유형이 아니므로 잘못된 사용 예외가 throw됩니다.

어디에서 감지 할 수 있습니까? 내 말은, 정확히 어떤 명령이 감지되었는지 에 있습니까? 캐스트 클래스 지침. 이것이 바로 castclass 명령어입니다.

내가 castclass 문자열 행을 생략하고 코드를 실행하려고하면 어떻게 될까요?

유형 안전 확인 프로그램이 프로그램을 거부했을 수 있습니다. 검증을 통과하지 않고 CLR을 강제 실행하면 정의되지 않은 동작이 발생합니다. 성공했을 수도 있고, 실패했을 수도 있고, 하드 디스크를 포맷했을 수도 있습니다.

실제로 새로운 참조를 만드나요?

구현 레벨에서 참조는 포인터 크기의 정수입니다. 메모리 관리자가 참조 된 데이터의 위치를 ​​추적하는 데 사용할 수있는 숫자입니다. 포인터 일 수도 있고 핸들 일 수도 있습니다. 이것은 레퍼런스의 추상 개념을 구현하는 것입니다.

변수가 12이고 "12"로 "대체"하는 경우 방금 생성 한 "새"12입니까, 아니면 "이전"12입니까? 두 번째 변수를 만들고 첫 번째 변수에서 복사하여 12를 입력한다고 가정하십시오. 그것은 "새로운"12인가 "오래된 것"12입니까? 어떻게 알 수 있니? 아무런 차이가없는 차이입니다. "이전"참조와 동일한 "새"참조를 만들면 새로운 것을 만드는 것입니까? 문제는 기술적 인 문제가 아니라 철학적 인 질문입니다.

+0

에릭, 아마도 직각으로 질문. 그러나 CastClass는 GetType() 런타임 유형 유추와 어떻게 비교됩니까? 둘 다 System.Reflection에 속하는 것 같습니다. 런타임 형식 호환성 (Equals 재정의 등)을 확인해야하는 경우에이를 캐스팅하거나 GetType == other.GetType()을 수행하는 것이 더 빠를 것이기 때문에 묻습니다. – Kakira

+0

@Kakira : 이것은 질의 응답 사이트입니다. 나는 당신이 당신의 질문을 논평이 아닌 질문으로 게시하는 것을 권장합니다! 그러나 당신의 질문이 "이 두 가지가 더 빠를 것"이라는 형태의 질문이라면 그런 다음 질문을 게시하지 마십시오. 두 가지 방법으로 코드를 작성하고 두 가지 방법으로 실행하면 어떤 것이 더 빠르는지 알 수 있습니다. –

+0

사과와 나는 당신의 요점을 본다. 나는 그것을 시험 할 것이다. CLR의 내부 동작에만 관심이 있었지만이 모든 것을 내 한 곳에서 찾을 수는 없습니다. :) – Kakira

4

당신은 인스턴스 참조를 혼동하고 있습니다. 새 참조이 만들어지며 새 인스턴스가 생성되지 않습니다. 문자열 "foo"

object foo = "bar"; 
string baz = (string)foo; 

새로운 참조baz 변수에 할당됩니다 (그러나 문자열의 하나 개의 인스턴스가 여전히 존재, 그것은 두 변수는 단일 인스턴스를 가리 단지입니다). 이 경우가 아니라면 "핸들"유형과 비슷한 것을 가질 수 있습니다. bazfoo 그대로 동일한 참조한다면,이 ..

foo = "bim"; 

도 (마찬가지로, 문자열이 아닌 유형을 할당하는 유효한 문자열 참조에 baz 더 이상 지점을 만들 것입니다) baz 동일한 "bim"에를 만들 것이다.

참조 유형이 동일한 상속 계층 (직접 또는 간접적으로 상속)이거나 유형 간의 명시적인 변환이 존재할 때 참조 유형에 대한 형변환을 수행 할 수 있습니다. 명시 적 변환은 다른 모든 연산자와 마찬가지로 다형성이 아닙니다. 즉, 변환 은 계층 구조의 다른 지점이 아닌 질문의 클래스 중 하나에서 구체적으로 정의되어야합니다.

명시 적 변환이있는 경우 해당 유형이 문제없이 호환되는 경우에도 우선 순위가 적용됩니다.명시 적 변환의 경우 캐스팅/변환 결과가 캐스팅되는 객체와 동일한 인스턴스를 가리킬 것이라는 보장은 없습니다 (실제로는 거의 없습니다).

+0

및 about : object obj = "abc"; string strA = "nothing"; strA = obj; 마지막 줄에 새로운 참조가 생깁니 까? 아니면 참조의 값이 "아무것도"의 주소에서 "abc"의 주소로 변경됩니까? –

+0

@devoured : 아래 캐스팅이 명시 적이어야하므로 나열한 코드는 컴파일되지 않습니다. 'obj = strA'는 컴파일되지만, 그렇다면'obj'가''abc''를 가리 키지 않고''nothing''을 가리키게됩니다. 같은 값을 가진 다른 참조입니다. 'ref' 매개 변수와 정상 매개 변수 사이의 구별이라고 생각하십시오. –

관련 문제