왜 int 변수 i가 아닌 short로 1을 전달할 수 있습니까?


146

첫 번째와 두 번째 쓰기는 왜 작동하지만 마지막은 작동하지 않습니까? 세 가지를 모두 허용하고 그것이 1, (int) 1인지 또는 내가 통과했는지 감지 할 수있는 방법이 있습니까? 그리고 실제로 왜 마지막이 허용됩니까? 두 번째는 허용되지만 마지막은 허용되지 않습니다.

컴파일 오류를 보여주는 데모

using System;
class Program
{
    public static void Write(short v) { }
    static void Main(string[] args)
    {
        Write(1);//ok
        Write((int)1);//ok
        int i=1;
        Write(i);//error!?
    }
}

2
나도 이것에 의해 혼란에 빠졌고, 함수 호출에서 int를 짧게 변환 해야하는 경우가 종종 있습니다 ...
Mathieu Dumoulin

2
@MathieuDumoulin은 주조 가능하므로 주조 할 수 있습니다. 그러나 그것은 손실 완전 변환이므로 (짧게 맞지 않는 많은 정수가 있기 때문에) 암시 적 캐스트는 불가능합니다 (short) i. 그래서 작성해야합니다 .
Abel

답변:


186

처음 두 개는 상수 식이고 마지막 두 개는 그렇지 않습니다.

C # 사양에서는 상수에 대해서는 int에서 short로 암시 적으로 변환 할 수 있지만 다른 식에는 사용할 수 없습니다. 상수의 경우 컴파일러에서 값이 대상 유형에 맞는지 확인할 수 있지만 일반 표현식에는 적합하지 않으므로 합리적인 규칙입니다.

이 규칙은 암시 적 변환은 무손실이어야한다는 지침에 따릅니다.

6.1.8 암시 적 상수 표현식 변환

암시 적 상수 표현식 변환은 다음 변환을 허용합니다.

  • 일정한 표현 유형 (§7.18)이 int형식으로 변환 할 수 sbyte, byte, short, ushort, uint, 또는 ulong상기 값 제공된 정전류 식 대상 유형의 범위이다.
  • 일정한 표현 유형은 long유형으로 변환 할 수 ulong의 값을 제공하는, 일정한 표현이 음수 아니다.

(C # 언어 사양 버전 3.0에서 인용)


67

로부터 암시 적 변환이 없습니다 intshort인해 절단의 가능성은. 그러나 상수 표현식컴파일러에 의해 대상 유형으로 취급 될 수 있습니다 .

1? 문제가되지 않습니다 : 분명히 유효한 short값입니다. i? 그다지 많지 않습니다. short.MaxValue예를 들어 어떤 값일 수 있으며 컴파일러는 일반적인 경우이를 확인할 수 없습니다.


그래서 ... 얼마나 명백한지는 중요하지 않습니다 ...> _ <. 리터럴이 전달되었는지 또는 int 변수인지 감지 할 수 있는지 알고 있습니까?

@ acidzombie24 당신은 할 수 없습니다. 그러나 왜 그렇게 하시겠습니까?
Adam Houldsworth

@ acidzombie24 나는 당신이 그것을 감지 할 수 있다고 생각하지 않습니다. 당신은 할 수 있지만 그 형태에서 얻을 반사를 사용하여 다음 템플릿 인수를 사용합니다.
Konrad Rudolph

3
@ acidzombie24 런타임 중에 리터럴을 전달할 수있는 방법이 없습니다. 따라서 컴파일 타임에 눈을 사용하여 확인할 수 있습니다.
Justin

1
이 경우 인수를 Expression<Func<int>>? 로 받아들이는 것이 옵션 일까요? 그런 다음 함수를 전달 () => 1하거나 () => i함수 내부에서 전달 된 엔터티에 캡처 된 변수 또는 상수 값이 포함되어 있는지 검사 할 수 있습니다.
콘래드 루돌프

8

int 리터럴은 암시 적으로 변환 할 수 있습니다 short. 이므로:

당신은 암시 적으로 더 큰 저장 크기의 nonliteral 숫자 형식을 변환 할 수 없습니다 짧은

따라서 리터럴의 암시 적 변환이 허용되므로 처음 두 작업이 작동합니다.


3
대답이 약간 잘못되었습니다. 리터럴이 아닌 constant-expression을 사용해야 합니다 . 특히 두 번째 예는 리터럴 이 아닙니다 .
코드 InChaos

6

첫 번째 두 가지 리터럴 / 상수를 전달했기 때문에 세 번째로 정수를 전달할 때 자동 유형 변환이 없기 때문입니다.

편집 : 누군가 나를 이길!


3

리터럴 사이에 암시 적 변환 이 없기 때문에 유형은 더 큰 크기의 짧은 유형으로 .

암시 적 변환은 상수 표현에만 가능합니다.

public static void Write(short v) { }

당신이 integer인수로 가치를 전달할 때short

int i=1;
Write(i);  //Which is Nonliteral here

3

컴파일러가 코드 실패 이유 를 알려줍니다 .

cannot convert `int' expression to type `short'

여기에 당신이 물어봐야 할 질문이 있습니다 : 왜이 ​​전환이 실패합니까? "c # convert int short"를 googled하고 MS C # 페이지에서short 키워드 .

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

이 페이지에서 알 수 있듯이 더 큰 데이터 유형에서 내재 된 캐스트는 short리터럴에만 허용됩니다. 컴파일러는 리터럴이 범위를 벗어 났을 때를 알 수 있지만 그렇지 않은 경우 프로그램 논리에서 범위를 벗어난 오류를 피할 수 있다는 확신이 필요합니다. 그 확신은 캐스트에 의해 제공됩니다.

Write((short)i)

0

int-> short에서 변환하면 데이터가 잘릴 수 있습니다. 그 이유입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.