문제

Jesse Liberty의 학습 C# 책에서 그는 "한 유형의 개체는 다른 유형의 객체로 변환 될 수 있습니다.이를 주조라고합니다."

아래 코드에서 생성 된 IL을 조사하면 캐스트 된 과제가 변환 된 과제와 동일하지 않음을 분명히 알 수 있습니다. 전자에서는 권투/무 복원이 발생하는 것을 볼 수 있습니다. 후자는 변환 메소드에 대한 호출을 볼 수 있습니다.

나는 결국 그것이 바보 같은 의미 론적 차이일지도 모른다는 것을 알고 있지만 변환을위한 또 다른 단어 만 주조하고 있습니다. 나는 으르렁 거리는 것을 의미하지는 않지만, 나는 이것에 대한 다른 사람의 직감에 관심이 없다. 캐스팅과 변환이 같은지 확인하거나 거부하는 확실한 참조를 지적 할 수 있습니까?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

고맙습니다

RP

명시 적/암시 적에 대한 Matt의 의견 후에 참고 :

나는 암시 적/명시 적이 차이라고 생각하지 않습니다. 내가 게시 한 코드에서, 변경은 두 경우 모두 명시 적입니다. 암시 적 변환은 int에 단락을 할당 할 때 발생하는 것입니다.

sklivvz에 대한 참고 :

나는 Jesse Liberty (일반적으로 명확하고 명확한) 언어의 느슨함에 대한 나의 의심이 옳았다는 것을 확인하고 싶었습니다. 나는 Jesse Liberty가 그의 언어로 약간 느슨하다고 생각했습니다. 캐스팅은 객체 계층 구조로 라우팅되었다는 것을 이해합니다. 즉, 정수에서 문자열로 캐스트 할 수는 없지만 System.Exception에서 파생 된 사용자 정의 예외에서 System.Exception으로 캐스트 할 수 있습니다.

그러나 int에서 문자열로 캐스트하려고 할 때 컴파일러는 값을 "변환"할 수 없다고 알려줍니다. 어쩌면 제시는 내가 생각했던 것보다 더 정확할 것입니다!

도움이 되었습니까?

해결책

간단한 대답은 다음과 같습니다.

값 유형의 경우 캐스팅에는 진정으로 다른 유형으로 변환하는 것이 포함됩니다. 예를 들어:

float f = 1.5f;
int i = (int) f; // Conversion

캐스팅 표현식 UNBOX가 발생하면 결과가 작동한다고 가정합니다. 대개 상자에 있었던 것의 사본만이 같은 유형으로. 그러나 예외가 있습니다. 박스형 int에서 열거 (기본 유형의 int)로 Unbox를 Unbox 및 그 반대도 마찬가지입니다. 마찬가지로 박스형 int에서 nullable로 Unbox를 사용할 수 있습니다.u003Cint> .

주조 표현식이 한 참조 유형에서 다른 참조 유형으로이고 사용자 정의 변환이 관련되지 않으면 객체 자체에 관한 한 변환이 없습니다. 참조 "변경" - 이는 참조 자체가 아니라 값이 간주되는 방식 일뿐입니다 (이전과 동일한 비트가 될 것입니다). 예를 들어:

object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object

사용자 정의 전환이 참여하면 대개 다른 객체/값을 반환하는 것을 수반합니다. 예를 들어, 자신의 유형에 대한 문자열로의 변환을 정의 할 수 있으며, 이는 확실히 자신의 객체와 동일한 데이터가 아닙니다. (물론 객체에서 이미 언급 된 기존 문자열 일 수 있습니다.) 내 경험에서 사용자 정의 변환은 일반적으로 참조 유형이 아닌 값 유형간에 존재하므로 거의 문제가되지 않습니다.

이 모든 것은 사양 측면에서 변환으로 계산됩니다. 그러나 그들은 모두 변환하는 것으로 간주되는 것은 아닙니다. 물체물체 다른 유형의. 나는 이것이 Jesse Liberty가 용어로 느슨한 경우라고 생각합니다. 나는 방금 읽고있는 C# 3.0을 프로그래밍 할 때 나타났습니다.

그게 모든 것을 다루나요?

다른 팁

절대적으로하지!

변환은 "가능한 모든 수단"을 통해 int32를 얻으려고 시도합니다. 캐스트는 그런 종류의 일을하지 않습니다. 캐스트와 함께 컴파일러에 변환없이 객체를 int로 처리하도록 지시합니다.

객체가 int32 또는 int32에 캐스팅 연산자가있는 다른 클래스라는 것을 알 때 항상 캐스트를 사용해야합니다 (예 : 플로트 등).

변환은 문자열 또는 다른 클래스와 함께 사용해야합니다.

이 시도

static void Main(string[] args)
{
    long l = long.MaxValue;

    Console.WriteLine(l);

    byte b = (byte) l;

    Console.WriteLine(b);

    b = Convert.ToByte(l);

    Console.WriteLine(b);

}

결과:

9223372036854775807

255

처리되지 않은 예외 :

System.OverFlowException : 값은 BYTE.MAXVALUE보다 크거나 BYTE.MINVALUE에서 SYSTEM.CONVERT.TOBYTE (int64 value) [0x00000] Test.Main (System.String [] args) [0x00019] In /Home /Marco에서 BYTE.MINVALUE보다 크다. /develop/test/exceptions.cs:15

내가 본 가장 좋은 설명은 아래에서 볼 수 있으며 소스에 대한 링크를 볼 수 있습니다.

"... 진실은 그보다 조금 더 복잡합니다. .net은 A 지점에서 B 지점으로가는 세 가지 방법을 제공합니다.

첫째, 암시 적 캐스트가 있습니다. 이것은 과제 이상의 것을 할 필요가없는 캐스트입니다.

int i = 5;
double d = i;

이것들은 "확대 변환"이라고도하며 .NET은 정보를 잃을 수 없기 때문에 캐스트 연산자없이 수행 할 수 있습니다. 이중의 가능한 유효한 값 범위는 int에 대한 유효한 값의 범위를 포함합니다. 일부는이 과제를 수행하지 않을 것입니다. 그런 다음 런타임이 int 값에서 몇 자릿수를 떨어 뜨렸다는 것을 공포에 알게 될 것입니다. 참조 유형의 경우, 암시 적 캐스트의 배후에있는 규칙은 캐스트가 잘못된 캐스트 소집을 던질 수 없다는 것입니다. 캐스트가 항상 유효하다는 것이 컴파일러에게 명확합니다.

자신의 유형에 대해 새로운 암시 적 캐스트 오퍼레이터를 만들 수 있습니다 (즉, 어리석은 경우 모든 규칙을 어기는 암시 적 캐스트를 만들 수 있음을 의미합니다). 기본적인 규칙은 암시 적 캐스트가 전환에 정보를 잃을 가능성을 포함 할 수 없다는 것입니다.

기본 표현에 유의하십시오 했다 이 변환의 변화 : 더블은 int와 완전히 다르게 표현됩니다.

두 번째 종류의 변환은 명백한 캐스트입니다. 정보를 잃을 가능성이 있거나 캐스트가 유효하지 않을 수있는 가능성이 있으므로 유효한 캐스트가 필요합니다.

double d = 1.5;
int i = (int)d;

여기에서 당신은 분명히 정보를 잃을 것입니다. 캐스트 후 1 살이되므로 0.5가 손실됩니다. 이것을 "좁은"변환이라고도하며 컴파일러는 명시 적 캐스트 (int)를 포함하여 예, 정보가 손실 될 수 있음을 알고 있지만 신경 쓰지 않는다는 것을 나타냅니다.

마찬가지로, 참조 유형을 사용하면 컴파일러는 런타임에 캐스트가 유효하지 않을 수있는 상황에서 명시 적 캐스트가 필요합니다. 예, 위험이 있다는 것을 알지만 당신이하고있는 일을 알고 있다는 신호입니다.

세 번째 변환은 디자이너가 명시적인 캐스트조차 제공하지 않는 표현의 급진적 인 변화를 포함하는 전환입니다. 그들은 변환을하기 위해 방법을 호출하게합니다.

string s = "15";
int i = Convert.ToInt32(s);

여기에 메소드 호출이 필요한 것은 없습니다. 암시적이고 명백한 캐스트는 메소드 호출입니다 (그렇기 때문에 직접 만드는 방법). 디자이너는 문자열을 int로 변환하는 명백한 캐스트 연산자를 쉽게 만들 수있었습니다. 방법을 부르는 요구 사항은 언어의 기본 요구 사항이 아닌 스타일 선택입니다.

스타일의 추론은 다음과 같은 일입니다. String-to-Int는 끔찍하게 잘못 될 수있는 많은 기회와 함께 복잡한 전환입니다.

string s = "The quick brown fox";
int i = Convert.ToInt32(s);

따라서 메소드 호출은 읽을 수있는 문서화를 제공하며, 이것이 단순한 캐스트 이상의 것이라는 광범위한 힌트를 제공합니다.

자신의 유형 (특히 자체 값 유형)을 설계 할 때는 캐스트 연산자 및 변환 기능을 작성하기로 결정할 수 있습니다. "암시 적 캐스트", "명시 적 캐스트"및 "전환 기능"영토를 나누는 라인은 약간 흐릿하므로 다른 사람들이 무엇이되어야하는지에 대해 다른 결정을 내릴 수 있습니다. 정보 손실과 예외 및 유효하지 않은 데이터의 가능성을 염두에두고 결정하는 데 도움이 될 것입니다. "

  • 브루스 우드, 2005 년 11 월 16 일

http://bytes.com/forum/post1068532-4.html

캐스팅에는 참조가 포함됩니다

List<int> myList = new List<int>();
//up-cast
IEnumerable<int> myEnumerable = (IEnumerable<int>) myList;
//down-cast
List<int> myOtherList = (List<int>) myEnumerable;

요소 추가와 같은 MyList에 대한 작업은 MyEnumerable 및 MyOtherlist에 반영됩니다. 이는 모두 같은 인스턴스에 대한 모든 유형의 참조이기 때문입니다.

업 캐스트는 안전합니다. 프로그래머가 유형에서 실수를 한 경우 다운 캐스팅은 런타임 오류를 생성 할 수 있습니다. 안전한 다운 캐스트는이 답변의 범위를 벗어납니다.

변환에는 인스턴스가 포함됩니다

List<int> myList = new List<int>();
int[] myArray = myList.ToArray();

MyList는 MyArray를 생산하는 데 사용됩니다. 이것은 비파괴 변환입니다 (이 작업 후에 MyList는 완벽하게 잘 작동합니다). 또한 요소 추가와 같은 MyList에 대한 작업은 MyArray에 반영되지 않습니다. 이것은 완전히 별도의 인스턴스이기 때문입니다.

decimal w = 1.1m;
int x = (int)w;

C#의 Cast Syntax를 사용하는 작업이 있습니다. 실제로 변환.

시맨틱은 제쳐두고, 빠른 테스트를 보여줍니다 동등하지 않습니다!
그들은 작업을 다르게 수행합니다 (또는 아마도 다른 작업을 수행합니다).

x=-2.5 (int)x=-2 Convert.ToInt32(x)=-2
x=-1.5 (int)x=-1 Convert.ToInt32(x)=-2
x=-0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 1.5 (int)x= 1 Convert.ToInt32(x)= 2
x= 2.5 (int)x= 2 Convert.ToInt32(x)= 2

주목하십시오 x=-1.5 그리고 x=1.5 케이스.

캐스트는 컴파일러/간호사에게 실제로 객체가 실제로 해당 유형의 경우 (또는 해당 유형의베이스 타입/인터페이스를 가지고 있음)를 알려줍니다. 더 이상 작업을 수행하는 컴파일러/간호사가 아닌 컨버터링에 비해 꽤 빠른 일입니다.

캐스팅은 항상 객체의 데이터 유형을 변경하는 것을 의미합니다. 예를 들어 플로트 값을 정수 값으로 변환하거나 비트를 재 해석하여 수행 할 수 있습니다. 일반적으로 언어 지원 (읽기 : 컴파일러 지원) 작업입니다.

"변환"이라는 용어는 때때로 캐스팅에 사용되지만 일반적으로 일부 라이브러리 또는 자체 코드에 의해 수행되며 반드시 캐스팅과 동일한 것은 아닙니다. 예를 들어, 제국 무게 값이 있고 메트릭 중량으로 변환하는 경우 동일한 데이터 유형 (예 : 플로트)을 유지하지만 다른 숫자가 될 수 있습니다. 또 다른 전형적인 예는 정도에서 라디안으로 변환하는 것입니다.

언어- / 프레임 워크 말하기의 말하기 방식으로, 한 유형이나 클래스에서 다른 유형으로 변환하는 것은 다음과 같습니다. 주조. 처음 네 줄이 표시되는 것처럼 .NET에게도 마찬가지입니다.

object x;
int y;

x = 4;

y = ( int )x;

C 및 C와 같은 언어 (예 : C#) 사용 (newtype)somevar 캐스팅을위한 구문. 예를 들어 VB.NET에는 이에 대한 명백한 내장 기능이 있습니다. 마지막 줄은 다음과 같이 작성됩니다.

y = CInt(x)

또는 더 복잡한 유형의 경우 :

y = CType(x, newtype)

'C'는 분명히 '캐스트'가 짧습니다.

.NET도 있습니다 Convert() 그러나 기능. 이것은 위의 두 가지와 달리 내장 언어 기능이 아니라 프레임 워크 중 하나입니다. .NET과 함께 반드시 사용되지 않는 언어를 사용할 때 더 명확 해집니다. Convert().

Matt가 말했듯이 행동의 차이는 Convert() 더 명확합니다. 컴파일러에게 처리하라고 말하는 대신 y 정수로서 x, 당신은 구체적으로 그것을 바꾸라고 말하고 있습니다 x 정수 클래스에 적합한 방식으로 그 다음에 결과를 할당하십시오 y.

특정한 경우 캐스팅은 'Unboxing'이라고 불리는 것을 수행하는 반면 Convert() 실제로 정수 값을 얻습니다. 결과는 동일하게 보이지만 미묘한 차이가 더 좋습니다. Keith가 설명했습니다.

표 1-7에 따르면 1 장의 55 페이지의 "명시적인 변환 방법"이라는 제목의 제목 MCTS 자체 진행중인 교육 키트 (Exam 70-536) : Microsoft® .NET Framework 2.0 — Application Development Foundation, 분명히 그들 사이에는 차이가 있습니다.

System.convert 언어 독립적이고 "구현하는 유형간에 변환됩니다. System.ICONVERTIBLE 인터페이스."

(유형) 캐스트 오퍼레이터 a C#-특이 적 정의하는 유형간에 변환하는 언어 기능 전환 연산자."

또한 사용자 지정 변환을 구현할 때 조언은 다릅니다 그들 사이에.

제목에 따라 사용자 정의 유형에서 변환을 구현하는 방법 위에서 인용 한 수업에서 56-57 쪽, 변환 연산자 (캐스팅).

선택한 기술은 수행하려는 변환 유형에 따라 다릅니다.

  • 정의하다 전환 연산자 숫자 유형 간의 좁은 전환 및 확대 전환을 단순화합니다.

  • 구현하다 System.ICONVERTIBLE System.Convert를 통해 변환을 가능하게합니다. 이 기술을 사용하여 문화 별 변환을 가능하게하십시오.

  • ...

캐스트 변환 연산자가 상상할 수있는 인터페이스와 별도로 구현되므로 convert ()가 반드시 캐스팅의 다른 이름 일 필요는 없다는 것이 명확해야합니다. (그러나 일관성을 보장하기 위해 한 구현이 다른 구현이 다른 구현을 참조 할 수있는 위치를 상상할 수 있습니다).

변수를 캐스팅하고 변환하는 다른 방법을 잊지 마십시오 : AS, Parse, TryParse 및 호환 가능한 데이터 유형 간의 암시 적 캐스팅.

이 사이트에는 대부분의 방법에 대한 출력이 좋은 샘플이 있습니다.C# 권투 및 개봉

따라서 이러한 샘플 변수를 감안할 때 :

int i = 3, x;
long l;
string s = "5";

기본적으로 두 가지 호환 유형 사이에 암시 적 주조를 가질 수 있습니다.

l = i;

Unboxing 또는 the를 사용한 명시 적 주조 ~처럼 예어:

s = (string)i;
//or
s = i as string;

System.Convert의 메소드를 사용한 명시 적 변환 :

i = System.Convert.ToInt32(s);

정의 된 데이터 유형의 메소드를 사용하여 명시 적 변환 :

i = int.Parse(s);
i = int.TryParse(s, x);

변수 인스턴스의 메소드를 사용하여 명시 적 변환 :

s = i.ToString();

제 생각에는 주조 단순히 두 가지 호환 유형 사이에 과제를 만드는 방법입니다.

변환 하나의 호환되지 않는 유형에서 다른 유형으로 명시 적으로 값을 복사 해야하는 경우 신뢰할 수 없습니다. 악한 강요.

MSDN에 대한 몇 가지 좋은 정보 : 캐스팅 및 유형 변환

캐스팅은 본질적으로 런타임에 "척"을 "척"이라고 말합니다. 실제로 어떤 식 으로든 개체를 변환하거나 변경하지 않습니다.

그러나 변환은 한 유형을 다른 유형으로 바꾸는 작업을 수행합니다.

예로서:

char caster = '5';
Console.WriteLine((int)caster);

모든 런타임은 비트 패턴을보고 int로 취급하기 때문에 해당 진술의 출력은 53입니다. 당신이 얻는 것은 숫자 5가 아닌 문자 5의 ASCII 값입니다.

그러나 convert.toint32 (캐스터)를 사용하는 경우 실제로 문자열을 읽고 올바르게 수정하기 때문에 5가 얻을 수 있습니다. (본질적으로 ASCII 값 53이 실제로 정수 값 5라는 것을 알고 있습니다.)

차이는 변환이 암시 적이든 명시 적인지 여부입니다. 첫 번째는 캐스트가 있고 두 번째는 캐스트가 변환되는 함수를보다 명확하게 호출하는 것입니다. 그들은 아마도 다른 방식으로 같은 일을하고있을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top