Programing

캐스팅과 Convert.To () 메서드 사용의 차이점

lottogame 2020. 10. 27. 07:46
반응형

캐스팅과 Convert.To () 메서드 사용의 차이점


나는 캐스트 기능이 doublestring값을.

string variable = "5.00"; 

double varDouble = (double)variable;

코드 변경이 체크인되었으며 프로젝트가 오류와 함께 빌드됩니다. System.InvalidCastException: Specified cast is not valid.

그러나 다음을 수행하면 ...

string variable = "5.00"; 

double varDouble = Convert.ToDouble(variable);

... 프로젝트는 오류없이 빌드됩니다.

캐스팅과 Convert.To()방법 사용의 차이점은 무엇입니까 ? 캐스팅은 왜 던지고 Exception사용 Convert.To()하지 않습니까?


어떻게 든 동등하다고 볼 있더라도 목적이 완전히 다릅니다. 먼저 캐스트가 무엇인지 정의 해 보겠습니다.

캐스팅은 한 데이터 유형의 엔티티를 다른 유형으로 변경하는 작업입니다.

캐스트는 종종 동일한 변환 구문을 갖기 때문에 약간 일반적이며 변환 과 동일합니다. 그러므로 질문은 언어에서 캐스트 (암시 적 또는 명시 적)가 허용되는시기와 사용해야하는 시기 여야합니다. 명시 적 전환?

먼저 그들 사이에 간단한 선을 그리 겠습니다 . 형식적으로 (언어 구문과 동일하더라도) 캐스트는 유형을 변경하는 반면 변환은 값을 변경하거나 변경할 수 있습니다 (결국 유형 함께). 또한 캐스트는 되돌릴 수 있지만 변환은 불가능할 수 있습니다.

이 주제는 매우 방대하므로 게임에서 커스텀 캐스트 연산자를 제외하여 조금 좁혀 보겠습니다.

암시 적 캐스트

C #에서는 정보를 잃지 않을 때 캐스트가 암시 적 입니다 (이 검사는 실제 값이 아닌 형식 으로 수행 됩니다 ).

기본 유형

예를 들면 :

int tinyInteger = 10;
long bigInteger = tinyInteger;

float tinyReal = 10.0f;
double bigReal = tinyReal;

변환 중에 정보를 잃지 않을 것이기 때문에 이러한 캐스트는 암시 적입니다 (유형을 더 넓게 만들기 만하면 됨). 그 반대의 경우 암시 적 캐스트는 허용되지 않습니다. 실제 값에 관계없이 (런타임에만 확인할 수 있기 때문에) 변환 중에 일부 정보가 손실 될 수 있기 때문입니다. 예를 들어이 코드는 다음 double과 같이 표현할 수없는 값을 포함 할 수 있기 때문에 컴파일 되지 않습니다 float.

// won't compile!
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때문에 당신이 만드는 캐스트와의 원시적 형태의 또 다른 유형의 새 개체를 ) 무엇을 변경하는 것은이다 보기 그들.

명시 적 캐스트

변환이 컴파일러에 의해 암시 적으로 수행되지 않은 경우 캐스트는 명시 적이며 캐스트 연산자를 사용해야합니다. 일반적으로 다음을 의미합니다.

  • 정보 나 데이터를 잃을 수 있으므로 알고 있어야합니다.
  • 변환이 실패 할 수 있습니다 (한 유형을 다른 유형으로 변환 할 수 없기 때문에). 따라서 수행중인 작업을 인식해야합니다.

기본 유형

변환 중에 일부 데이터가 손실 될 수있는 경우 기본 유형에 대해 명시 적 캐스트가 필요합니다. 예를 들면 다음과 같습니다.

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에서 올 수 있음). 귀하의 예로 돌아가십시오.

// won't compile!
string text = "123";
double value = (double)text;

컴파일러가 텍스트를 숫자로 변환 할 수 없기 때문에 컴파일되지 않습니다. 텍스트에는 숫자뿐만 아니라 모든 문자가 포함될 수 있으며 C #에서는 명시 적 캐스트의 경우에도 너무 많습니다 (하지만 다른 언어에서는 허용 될 수 있음).

사물

유형이 관련이없는 경우 포인터에서 객체로의 변환이 실패 할 수 있습니다. 예를 들어이 코드는 컴파일되지 않습니다 (컴파일러는 가능한 변환이 없음을 알고 있기 때문입니다).

// won't compile!    
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; // Equals to Nullable<float> maybe = 10;
float sure1 = (float)maybe; // With cast
float sure2 = maybe.Value; // Without cast

이 경우 실패 할 수 있기 때문에 명시 적이지만 이는 구현에 맡겨집니다 (이에 대한 지침이 있더라도). 다음과 같은 사용자 지정 문자열 클래스를 작성한다고 가정 해보십시오.

EasyString text = "123"; // Implicit from string
double value = (string)text; // Explicit to double

구현에서 "프로그래머의 삶을 더 쉽게 만들기"를 결정하고 캐스트를 통해이 변환을 노출 할 수 있습니다 (단순히 작성하는 지름길 일뿐임을 기억하십시오). 일부 언어는이를 허용 할 수도 있습니다.

double value = "123";

모든 유형에 대한 암시 적 변환 허용 (확인은 런타임에 수행됨). 적절한 옵션을 사용하면 예를 들어 VB.NET에서이 작업을 수행 할 수 있습니다. 그것은 단지 다른 철학입니다.

그들로 무엇을 할 수 있습니까?

그래서 마지막 질문은 언제 하나 또는 다른 것을 사용해야 하는가입니다. 언제 명시 적 캐스트를 사용할 수 있는지 살펴 보겠습니다.

  • 기본 유형 간의 변환.
  • 에서 object다른 유형으로의 변환 (개봉도 포함될 수 있음).
  • 파생 클래스에서 기본 클래스 (또는 구현 된 인터페이스) 로의 변환.
  • 사용자 지정 변환 연산자를 통해 한 유형에서 다른 유형으로의 변환.

첫 번째 변환 만 수행 할 수 있으므로 Convert선택의 여지가없고 명시 적 캐스트를 사용해야합니다.

이제 언제 사용할 수 있는지 보겠습니다 Convert.

  • 모든 기본 유형에서 다른 기본 유형으로의 변환 (몇 가지 제한 사항이 있음, MSDN 참조 ).
  • IConvertible다른 (지원되는) 유형으로 구현되는 모든 유형에서 변환 .
  • byte배열에서 문자열로 /에서 변환 .

결론

IMO Convert는 변환이 실패 할 수 있음을 알 때마다 (형식, 범위 또는 지원되지 않을 수 있기 때문에) 캐스트로 동일한 변환을 수행 할 수있는 경우에도 사용해야합니다 (다른 것을 사용할 수없는 경우). 누가 여러분의 코드를 읽을 것인지 , 그리고 그것이 실패 할 수 있다는 것을 분명히합니다 (디버그 단순화).

캐스트를 사용해야하는 다른 모든 경우에는 선택의 여지가 없지만 다른 더 나은 방법을 사용할 수 있으면 사용하는 것이 좋습니다. 당신의 예에서의 변환 string에는 double가능한 한 (또한 당신이 그것을보다 효율적으로 제어를 얻을 수) 명시 적으로 많이 그것을해야하므로 매우 자주 사용 예를 들어, 실패합니다 (텍스트가 사용자로부터 온다 특히)하는 것이 뭔가 TryParse방법을.

편집 : 그들 사이의 차이점은 무엇입니까?

(대한 업데이트 된 질문에 따라 그리고 내가 전에 쓴 유지 하면 당신은 / 사용 할 수 있습니다 때에 비해 캐스트를 사용할 수 있습니다 Convert또한 (그들 사이의 차이가있는 경우입니다 명확히 다음 마지막 점) Convert용도 IConvertibleIFormattable인터페이스가 작업을 수행 할 수 있도록 캐스트와 함께 허용되지 않음).

짧은 대답은 그렇습니다. 그들은 다르게 행동합니다 . 나는 Convert클래스가 도우미 메서드 클래스와 같은 것으로 보아서 종종 약간의 이점 이나 약간 다른 동작을 제공합니다. 예를 들면 :

double real = 1.6;
int castedInteger = (int)real; // 1
int convertedInteger = Convert.ToInt32(real); // 2

꽤 다르죠? 캐스트 잘라 내기 (우리 모두가 예상하는 것임) Convert는 가장 가까운 정수로 반올림을 수행합니다 (알지 못하는 경우 예상되지 않을 수 있음). 각 변환 방법에는 차이가 있으므로 일반적인 규칙을 적용 할 수 없으며 사례별로 확인해야합니다 ... 19 가지 기본 유형을 다른 모든 유형으로 변환 할 수 있습니다 ... 목록은 꽤 길 수 있습니다. MSDN 사례를 참조하는 것이 훨씬 좋습니다. 케이스!


Casting is a way of telling the compiler, "I know that you think that this variable is a Bar, but I happen to know more than you; the object is actually a Foo, so let me treat it as if it were a Foo from now on." Then, at runtime, if the actual object turned out to really be a Foo then your code works, if it turns out that the object was not a Foo at all, then you get an exception. (Specifically an System.InvalidCastException.)

반면에 변환은 "Bar 유형의 객체를 주면 해당 Bar 객체에있는 것을 나타내는 새로운 Foo 객체를 만들 수 있습니다. 원래 객체를 변경하지 않을 것입니다." t는 것, 다르게 원래 개체를 치료 그냥 다른 값을 기준으로 새로운 무언가를 창조 . 그것이 그렇게하는 방법에 관해서는, 그것은 아무것도 될 수 있습니다.의 경우 Convert.ToDouble는 호출 끝날 것Double.Parse어떤 유형의 문자열이 어떤 숫자 값을 나타내는 지 결정하기위한 모든 종류의 복잡한 논리가 있습니다. 문자열을 다르게 double로 매핑하는 자체 변환 방법을 작성할 수 있습니다 (아마도 로마 숫자 등과 같은 숫자 표시에 대해 완전히 다른 규칙을 지원하기 위해). 변환은 무엇이든 할 수 있지만, 아이디어는 컴파일러에게 당신을 위해 아무것도하도록 요청하는 것이 아니라는 것입니다. 여러분의 도움없이 컴파일러는 a를 .NET에 매핑하는 방법을 알 수 없기 때문에 새 객체를 만드는 방법을 결정하는 코드를 작성 string하는 사람 double입니다.

그렇다면 언제 전환하고 언제 캐스팅합니까? 두 경우 모두 어떤 유형의 변수를 가지고 있고, A라고합시다. 그리고 우리는 B 유형의 변수를 원합니다. 우리의 A 객체가 실제로 실제로 B이면 우리는 캐스팅합니다. 실제로 B가 아니라면이를 변환하고 프로그램이 A로부터 B를 얻는 방법을 정의해야합니다.


Convert.Double메서드는 실제로 내부적으로 Double.Parse(string)메서드를 호출합니다 .

어느 String유형이나 Double캐스팅은 항상 실패 때문에 유형은 두 가지 유형 사이의 명시 적 / 암시 적 변환을 정의합니다.

Double.Parse메서드는의 각 문자를 살펴보고의 문자 string값을 기반으로 숫자 값을 string만듭니다. 잘못된 문자가 있으면 Parse메서드가 실패합니다 ( Convert.Double메서드도 실패 함).


귀하의 예에서 문자열을 double (비 정수 유형)으로 캐스트하려고 시도하고 있습니다.

작동하려면 명시 적 변환이 필요합니다.

그리고 나는 당신이 int로 변환 할 때 double 값의 소수 부분을 잃을 수 있기 때문에 Convert.ToDouble대신 사용할 수 있음을 지적해야합니다 Convert.ToInt64.

변수 값이 "5.25"인 경우 varDouble은 5.00 (Int64 로의 변환으로 인한 0.25 손실)이됩니다.

캐스팅과 변환에 대한 질문에 대답합니다.

Your cast (an explicit cast) doesn't meet the requirements for an explicit cast. the value you are trying to cast with the cast operator is invalid (i.e non integral).

Visit this MSDN Page for the rules of casting / conversions


Casting does not involve any conversion, i.e. the internal representation of a value is not changed. Example:

object o = "Hello"; // o is typed as object and contains a string.
string s = (string)o; // This works only if o really contains a string or null.

You can convert a double to string like this

double d = 5;
string s = d.ToString(); // -> "5"

// Or by specifying a format
string formatted = d.ToString("N2"); // -> "5.00"

You can convert a string to a double in several ways (here just two of them):

string s = "5";
double d = Double.Parse(s); // Throws an exception if s does not contain a valid number

Or the safe way

string s = "5";
double d;
if (Double.TryParse(s, out d)) {
    Console.WriteLine("OK. Result = {0}", d);
} else {
    Console.WriteLine("oops!");
}

From MSDN:

Explicit conversions (casts): Explicit conversions require a cast operator. Casting is required when information might be lost in the conversion, or when the conversion might not succeed for other reasons. Typical examples include numeric conversion to a type that has less precision or a smaller range, and conversion of a base-class instance to a derived class.

Consider the following example:

double a = 2548.3;
int b;
b = (int)a; //2548 --> information (.3) lost in the conversion

And also:

A cast is a way of explicitly informing the compiler that you intend to make the conversion and that you are aware that data loss might occur.

호환되지 않는 유형 System.Convert간에 변환하려는 경우 클래스를 사용할 수 있습니다. 큰 차이점 사이 주조변환이 있다 컴파일런타임 . 유형 변환 예외는 런타임 에 나타납니다 . 즉, 런타임에 실패한 유형 캐스트 는를 throw합니다.InvalidCastException


결론 : 캐스팅에서 당신은 컴파일러에게 a진짜 타입 b이고 만약 그렇다면 프로젝트는이 예제와 같이 오류없이 빌드 된다는 것을 말하고 있습니다 .

double s = 2;
int a = (int) s;

But in conversion you're saying to the compiler there is a way to create a new object from a of type b, please do it and project builds without any errors but as I said if type cast fails at run-time, it will cause an InvalidCastException to be thrown.

For example the code below is never compile because compiler detect that cannot cast expression of type DateTime to type int:

DateTime s = DateTime.Now;
int a = (int)(s);

But this one is compiled successfully:

DateTime s = DateTime.Now;
int a = Convert.ToInt32(s);

But at run-time you will get InvalidCastException which says:

Invalid cast from 'DateTime' to 'Int32'.


string variable = "5.00";     
double varDouble = (double)variable;

Above conversion is simply not allowed by language. Here is a list of explicit casts for numerical types: http://msdn.microsoft.com/en-us/library/yht2cx7b.aspx As you can see, even not every numerical type could be converted to another numerical type

Some more info about casting here

And how does this differ to Convert.ToDouble()?

When you cast a type, data structure is not changed. Well, in case of numerical values conversion it you may loose few bits or get few additional 0 bits. But you are still working with a number. You are just changing an amount of memory taken by that number. That is safe enough for compiler do everything needed.

But when you are trying to cast string to a number, you can't do that because it is not enough to change amount of memory taken by variable. For instance, 5.00 as a string is a sequence of "numbers":53(5) 46(.) 48(0) 48(0) - that is for ASCII, but string will contain something similar. If compiler will just take first N (4 for double? not sure) bytes from a string - that piece will contain completely different double number. At the same time Convert.ToDouble() run special algorithm which will take each symbol of a string, figure out digit which it represents and make a double number for you, if string represents a number. Languages like PHP will, roughly speaking, call Convert.ToDouble for you in background. But C#, like a statically typed language, will not do that for you. This allows you to be sure that any operation is type safe and you will not get something unexpected doing something like:

double d = (double)"zzzz"

Casting a string to a double like that is not allowed C# which is why you get an Exception, you need to have the string converted (MSDN doc that shows acceptable conversion paths). This is simply because a string isn't necessarily going to contain numeric data, but the various numeric types will (barring null values). A Convert will run a method that will check the string to see if it can be turned into a numeric value. If it can, then it will return that value. If it can't, it'll throw an exception.

To convert it, you have several options. You used the Convert method in your question, there's Parse which is largely similar to Convert, but you should also look at TryParse which would allow you to do:

string variable = "5.00"; 

double varDouble;

if (Double.TryParse(variable, out varDouble)) {
    //Code that runs if the conversion succeeded.
} else {
    //Code that runs if the conversion failed.
}

This avoids the possible exception should you try to Convert or Parse a non-numerical string.


double varDouble = (double)variable assumes that variable is already a double. If variable isn't a double (it's a string) then this will fail. double varDouble = Convert.ToDouble(variable) does like it says - it converts. If it can parse or otherwise extract a double from variable then it will.

I second using Double.Parse or Double.TryParse because it more clearly indicates what's supposed to be happening. You're starting with a string and expecting it to be convertible to a double. If there's any doubt, use TryParse.

If variable is a method argument, change the type to double. Make the caller responsible for providing the correct type. That way the compiler does the work for you.


The most important difference is that if type casting is used and the conversion fails (say we are converting a very big float value to int ) no exception will be thrown and the minimum value an int can hold will be shown. But in case of using Convert , an exception will be thrown for such scenarios.

참고URL : https://stackoverflow.com/questions/15394032/difference-between-casting-and-using-the-convert-to-method

반응형