"double val = 1;"의 차이점이 있습니까? 그리고 "double val = 1D;"?


17

다음 두 코드 조각간에 차이점이 있습니까?

class Test {

    public readonly double Val;

    public Test(bool src) {
        this.Val = src ? 1 : 0;
    }

}

class Test {

    public readonly double Val;

    public Test(bool src) {
        this.Val = src ? 1D : 0D;
    }

}

코드베이스가 두 번째 작성 방식을 사용한다는 것을 알았습니다.


내 머리 꼭대기에서 첫 번째는 길고 두 배의 승진이 필요합니다.
Tanveer Badar

2
먼저 암시 적 변환을 두 번으로 변환하고 두 번째는 변환하지 않습니다.
Serkan Arslan

2
질문 제목과 본문의 질문이 일치하지 않으며 두 질문의 답변이 다릅니다.
Eric Lippert

1
@Eric Lippert 실제로 질문 본문은 다른 사용자가 편집했습니다.
srnldai

1
@ 브라이언 : 아니요, 원래 포스터는 정확합니다. 편집은 질문의 의미를 바꾸었고, 나는 눈치 채지 못했습니다. 원래 질문은 "차이가 있습니까? 더 나아가 차이가 있습니까?"였습니다. 제거 된 "추가"는 원래 포스터 가 다른 답변이있을 수있는 두 가지 질문을한다는 것을 깨달았습니다 . 그것은 나쁜 습관입니다. 질문은 이상적으로 단일 질문을해야합니다. 그러나 편집은 두 개의 질문이 두 개의 다른 질문이 아니라 동일한 질문 인 것처럼 보이게합니다.
Eric Lippert

답변:


18

여기에는 두 가지 질문이 있으며 답변이 서로 다르다는 점에 유의하십시오.

double val = 1;와 사이에 차이가 double val = 1D;있습니까?

C # 컴파일러는 double이 예상되는 컨텍스트에서 정수 리터럴이 사용되는 시점을 인식하고 컴파일 타임에 유형이 변경되므로이 두 조각은 동일한 코드를 생성합니다.

다음 두 코드 조각간에 차이점이 있습니까?

double Val; 
...    
this.Val = src ? 1 : 0;
---
this.Val = src ? 1D : 0D;

예. 정수 상수가 자동으로 더블로 변경된다는 규칙은 적용 상수 , 그리고 src ? ...하지 않은 것입니다 상수 . 컴파일러는 작성한 것처럼 전자를 생성합니다.

int t;
if (src)
  t = 1;
else
  t = 0;
this.Val = (double)t;

그리고 두 번째

double t;
if (src)
  t = 1D;
else
  t = 0D;
this.Val = t;

즉, 첫 번째는 정수를 선택한 다음 두 배로 변환하고 두 번째는 두 배를 선택합니다.

참고 : C # 컴파일러 또는 지터가된다 허용 된 첫 번째 프로그램이 두 번째로 최적화 될 수 있다는 것을 인식하지만, 실제로 그렇게 나도 몰라. C # 컴파일러 때때로 해제에 대한 변환을 이동합니다. 산술에 조건부 본문으로 가 있습니다. 나는 약 8 년 전에 그 코드를 썼지 만 모든 세부 사항을 기억하지는 않습니다.


6

거기 이다 생성 IL 코드의 차이.

이 수업 :

class Test1
{
    public readonly double Val;

    public Test1(bool src)
    {
        this.Val = src ? 1 : 0;
    }
}

생성자를 위해이 IL 코드를 생성합니다.

.class private auto ansi beforefieldinit Demo.Test1
    extends [mscorlib]System.Object
{
    .field public initonly float64 Val

    .method public hidebysig specialname rtspecialname instance void .ctor (
            bool src
        ) cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldarg.1
        IL_0008: brtrue.s IL_000d

        IL_000a: ldc.i4.0
        IL_000b: br.s IL_000e

        IL_000d: ldc.i4.1

        IL_000e: conv.r8
        IL_000f: stfld float64 Demo.Test1::Val
        IL_0014: ret
    }
}

그리고이 수업은 :

class Test2
{
    public readonly double Val;

    public Test2(bool src)
    {
        this.Val = src ? 1d : 0d;
    }
}

생성자를 위해이 IL 코드를 생성합니다.

.class private auto ansi beforefieldinit Demo.Test2
    extends [mscorlib]System.Object
{
    .field public initonly float64 Val

    .method public hidebysig specialname rtspecialname instance void .ctor (
            bool src
        ) cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldarg.1
        IL_0008: brtrue.s IL_0015

        IL_000a: ldc.r8 0.0
        IL_0013: br.s IL_001e

        IL_0015: ldc.r8 1

        IL_001e: stfld float64 Demo.Test2::Val
        IL_0023: ret
    }
}

보시다시피, 첫 번째 버전에서는 conv.r8int를 double로 변환하기 위해 호출 해야합니다.

그러나 (1) 최종 결과는 동일하며 (2) JIT 컴파일러는이 두 가지를 모두 동일한 기계 코드로 변환 할 수 있습니다.

대답은 그래서 : 네, 있습니다 -하지만 당신은 걱정할 필요가없는 하나의 차이.

개인적으로, 나는 프로그래머의 의도를 더 잘 표현 하고 JIT 컴파일러가 얻는 것에 따라 매우 약간 더 효율적인 코드를 생성 할 수 있기 때문에 두 번째 버전으로 갈 것입니다 .


4

차이점은 없습니다. 컴파일러는 암시 적으로 변환을 수행 할 수있을만큼 똑똑합니다.
당신이 사용하는 경우 그러나 var, 당신이 작성해야 var val = 42D;할 것은 반드시 변수를 int 더블 및 아니다.

double foo = 1;  // This is a double having the value 1
double bar = 1d; // This is a double having the value 1

var val = 42d;   // This is a double having the value 42
var val2 = 42;   // /!\ This is an int having the value 42 !! /!\
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.