2012-02-14 4 views
4

다음 코드에서 varInt64으로 확인되지만 double으로 확인됩니다. 왜 그래야만하지?var가 Double이 아닌 Long으로 해석되는 이유는 무엇입니까?

string a = "1234"; 
bool asInt = true; 
var b = (asInt) ? Int64.Parse(a) : Double.Parse(a) ; 
Console.WriteLine(b.GetType()); 
+1

나는 심지어 컴파일하는 것에 놀라움을 금치 못했다. 나는 삼항의 양쪽이 같은 타입을 반환해야한다고 생각했지만, 잠시 동안 암묵적으로 대화하는 것이 의심된다. ​​ –

+0

있다. ,) 이것을 설명합니다. – TomTom

답변

12

암시 Int64에서 Double로 변환하지만 (인해 그 방향의 정밀도가 손실로) 다른 방법이있다.

조건부의 "분기"가 모두 동일한 유형으로 변환되어야하므로 b 유형은 Double으로 유추됩니다.

+0

의미가 있습니다. 필요한 경우 Int64 유형의 변수'b'를 만들 수있는 방법이 있습니까 (필요할 경우 bool 'asInt'를 기반으로)? 물론 if 문에서 초기화하는 것은 작동하지 않습니다. 블록의 범위가 제한되어 있기 때문입니다. – xbonez

+0

@xbonez - 조건부 연산자가 아닙니다. 유형은 런타임에 유추/결정되어야합니다. _ 동적으로 사용할 수 있습니다. – Oded

+0

흠 ... 고마워. 나는 역동적 인 것을 살펴볼 것이다. 나는 수학 연산이 복식에서 느리다는 것을 알고 있으므로, 필요하지 않을 때는 double을 사용하지 않기를 바랬다. 역동적 인 부분을 살펴 보겠습니다.하지만 작동하지 않는다면 나는 함께 살 것입니다. – xbonez

5

long을 내재적으로 double으로 전송할 수 있습니다.

당신은 암시 적으로 long

그래서 C# 컴파일러가 double했다 당신의 변수 유형에 대한 유일한 가능성을 결정했다 double에 캐스팅 수 없습니다.

Implicit Numeric Conversions Table을 참조하십시오.

4

컴파일러는 명시 적 캐스트를 요구하지 않고 Int64.Parse(a)Double.Parse(a)의 값을 모두 보유 할 수있는 유형을 유추해야하기 때문에 long이 유추 된 경우 다른 소수의 표현에서 정밀도가 손실됩니다. 당신이 유형을 구분해야하는 경우

, 당신은 변수를 선언하고 코드를 다시 작성해야 :

if (asInt) 
{ 
    var b = Int64.Parse(a); // will infer a `long` 
    Console.WriteLine(b.GetType()); 
} 
else 
{ 
    var b = Double.Parse(a); // will infer a `double` 
    Console.WriteLine(b.GetType()); 
} 
+1

그래서 if-else 스코프 밖에서 변수 b에 접근 할 수있는 방법이 있습니까? – xbonez

+0

@xbonez, 그렇습니다. 그러나'b'를'object' 타입으로 정의해야합니다 :'object b;' – Dims

+0

완벽 ... 이것은 내가 오랫동안 찾고 있었던 것입니다. 'Object'는 내가 필요한 것입니다. 고맙습니다! – xbonez

1

C# 컴파일러는 두 반환 형식 사이의 공통 분모에서 유형을 추론 귀하 세 개 한 벌. Int64는 암시 적으로 Double으로 변환 될 수 있습니다. 역은 그렇지 않습니다.

코드 예제의 부울 상태는 유추 된 형식과 아무 관련이 없습니다.

0

이것은 ?: 연산자의 작업입니다. 모든 결과를 하나의 유형으로 변환해야합니다.

P.

string a = "1234"; 
var b = Int64.Parse(a) + Double.Parse(a) ; 
Console.WriteLine(b.GetType()); 

P.P.와 비슷한 동작을 사용자는 알고 있습니다.

string a = "1234"; 
bool asInt = true; 
object b; 
if(asInt) b=Int64.Parse(a); else b=Double.Parse(a); 
Console.WriteLine(b.GetType()); 

P.P.P.S. : 당신은 당신이 object를 사용해야 원하는 것을하게하려면 또 다른 옵션은 다음과 같습니다

 string a = "1234"; 
#if asInt 
     Int64 b = Int64.Parse(a); 
#else 
     Double b = Double.Parse(a); 
#endif 
     Console.WriteLine(b.GetType()); 

이 asInt이

#define asInt 
+0

불행하게도,'object'는'Int64' 또는'double'으로 캐스팅해야만합니다. 어떤 작업을 수행하기 전에 런타임이 될 때까지 타입을 모르기 때문에 가능하지 않습니다. – xbonez

+0

그런 다음 조건부 컴파일을 시도하십시오 지시어,'# if' 등 – Dims

+0

또한 산술 연산자를 사용하지 않는 경우 제네릭 메소드 및/또는 유형을 사용할 수 있습니다. 그렇다면 더 많은 트릭을 할 것입니다. – Dims

0

놀랐 아무도 당신이 값이 법적long값이 될 것입니다 알고 경우, 당신은 변경할 수 있음을 지적하지 않았다있어 사용 정의 명시 적 캐스트를 사용하는 컴파일러의 동작은long을 사용하십시오.

이 값은 asInt의 값을 결정하는 조건에 따라, 그리고 표현식의 결과와 함께하려는 의도에 따라 유용 할 수도 있고 그렇지 않을 수도 있습니다. 예를 들면 다음과 같습니다.

string a = "1234.56"; 
bool asDouble = a.Contains("."); 
var b = asDouble ? (long)Double.Parse(a) : Int64.Parse(a); 
Console.WriteLine(b.GetType()); 

사실,이 예에서는 조건부 연산자가 필요 없습니다. 즉

string a = "1234.56"; 
var b = (long)Double.Parse(a); 
Console.WriteLine(b.GetType()); 

, 그것은 최선의 해결책은 삼항 연산자를 사용하지 것이 가능하지만, 문제는 알고 충분한 컨텍스트를 제공하지 않습니다이 너무 작동합니다.