2012-03-01 3 views
4
public void Foo(double d){ 
    // when called below, d == 2^32-1 
    ... 
} 
public void Bar(){ 
    uint ui = 1; 
    Foo(0 - ui); 
} 

0과 ui 모두 여기에서 서명 된 long으로 승격 될 것으로 예상됩니다.C# 0 (빼기) uint = 부호없는 결과?

이 uint로 캐스팅이 안전하다는 것을 컴파일 타임에 알 수있는 것입니다 리터럴 0

사실,

하지만이 모든 단지 잘못된 것 같아요. 최소한 경고를 발행해야합니다.

감사합니다.

언어 사양이 이렇게 모호한 경우가 있습니까?

+5

이 질문은 Jon Skeet을 기다립니다. –

+2

오랫동안 :-) –

답변

0

0에서 빼기를 수행하려면 uint으로 캐스트되는 int입니다 (이것은 컴파일러에서 암시 적으로 uint으로 해석됩니다). int ~ uint은 암시 적 변환이므로 경고가 아닙니다. 코드에 아무런 문제가 없습니다 ... uint은 CLS 컴파일러가 아닙니다. 왜 here을 읽을 수 있습니다. MSDN

+1

'int'에서'uint' 로의 변환은 일반적으로 암시 적 변환이 아닙니다. 이는 암시 적 상수 표현식 변환 *입니다. 사양의 섹션 6.1.9를 참조하십시오. 우리가'int' * 변수로 시작했다면,'long'으로 승진했을 것입니다. (int와 uint 모두 암시 적으로 long으로 변환 될 수 있습니다.) –

+0

@ JonSkeet 명확한 설명 주셔서 감사합니다 :) – SiliconMind

+0

내 혼란의 근본 원인은 단순히 0이 내재적으로 uint로 변환 될 수 있기 때문에이 대답을 수락하는 것입니다. 나는 0이 int라는 가정에 근거하여 오랫동안 프로모션을 기대했다. – mike

7

long으로 홍보하는 이유는 무엇입니까? 상수 값 0가 암시 적으로 변환이라고

  • int operator-(int x, int y);
  • uint operator-(uint x, uint y);
  • long operator-(long x, long y);
  • ulong operator-(ulong x, ulong y);

을 감안할 때 : 사양 (섹션 7.8.5)는 정수 빼기를위한 네 개의 연산자를 나열 uint이지만 uintui이고은 암시 적으로 int으로 변환 가능하며 두 번째 연산자는 7.3.4 절에 설명 된 이진 연산자 과부하 해결 단계에 따라 선택됩니다.

(당신이 0에서 uint과 그 혼란 부분임을 암시 적 상수 식 변환의 인식이라고 할 수 있습니까? 자세한 내용은 C# 4 사양의 섹션 6.1.9을 참조하십시오.)

섹션에 따라 7.3.4 (7.3.5 및 7.5.3을 참조)는 약간 구불 구불하지만, 잘 정의되어 있으며 모호하지는 않습니다.

너를 귀찮게하는 오버플로 인 경우 도 실패 할 것으로 예상하십니까?

int x = 10; 
int y = int.MaxValue - 5; 
int z = x + y; 

그렇지 않을 경우, 여기 정말 차이가 무엇입니까?

+0

나는 그의 문제가 (모호한) 결과 값에 더 가깝다고 생각합니다. 즉 0에서 양수를 빼면 긍정적 인 결과를 얻지 않아야합니다. 마찬가지로 int 예제에서 양수에 10을 더하면 음수가되어서는 안됩니다. 만약 당신이이 유형의 경계를 당신의 숫자에 대해 다루는 것이라면, 당신의 결과가 모호하지 않다는 것을 확인하기 위해'checked'를 사용하는 것이 가장 좋을 것 같지 않습니다. (최소한 모호합니다) – NominSim

+0

@NominSim : 저기 있습니다. 애매 모호함. 명세가 지시 한대로 * 동작합니다. OP가 확인 된 컨텍스트를 사용하기를 원한다면 절대적으로 할 수 있지만 여기서 경고 할 필요는 없으며 모든 것이 올바르게 작동합니다. OP의 실제 문제는''uint' 산술로 수행된다는 것인데,'long' 산술을 사용하기를 기대한다고 생각합니다. "0과 ui가 모두 여기 서명 된 longs로 승격 될 것으로 기대합니다." –

+0

필자는 명세가 규정 한대로 정확하게 작동한다는 것을 알게되었습니다. 모호함은 사양에 없지만 음수에서 보장 된 양수를 뺀다면, 음수 결과를 얻어야합니다. 그렇기 때문에 특정 데이터 구조의 범위를 벗어나는 숫자를 처리하는 경우 OP가 체크 된 컨텍스트를 사용해야한다고 생각하는 이유입니다. – NominSim

0

의 CLS 컴파일 코드에 대한 자세한 내용 확인 된 컨텍스트에서 차이가 결과 형식의 범위 밖에 있으면 System.OverflowException이 throw됩니다. 점검되지 않은 컨텍스트에서는 오버플로가보고되지 않고 결과 유형 범위 밖에있는 중요한 상위 비트가 무시됩니다.

http://msdn.microsoft.com/en-us/library/aa691376(v=vs.71).aspx

기술적으로는, 수행은 다음 :

double d = checked(0-ui); 

이 체크되지 않기 때문에 당신이 기대하지만, 사양에 따라 있습니다 아마도 무엇 인 System.OverflowException의 투사가 발생합니다 오버 플로우가 보고되지 않았다.