동적 (C # 4)과 var의 차이점은 무엇입니까?


199

C # v4와 함께 제공되는 새 키워드에 대한 많은 기사를 읽었지만 "동적"과 "var"의 차이점을 알 수 없었습니다.

이 기사 는 그것에 대해 생각하게 만들었지 만 여전히 차이점을 볼 수는 없습니다.

"var"을 로컬 변수로만 사용할 수 있고 로컬 및 글로벌 모두로 동적으로 사용할 수 있습니까?

동적 키워드없이 일부 코드를 표시 한 다음 동적 키워드로 동일한 코드를 표시 할 수 있습니까?

답변:


455

var정적 유형입니다-컴파일러와 런타임 은 유형을 알고 있습니다 -입력을 저장하면됩니다 ... 다음은 100 % 동일합니다.

var s = "abc";
Console.WriteLine(s.Length);

string s = "abc";
Console.WriteLine(s.Length);

일어난 모두는 것이 었습니다 컴파일러는 것을 알아 냈 s(이니셜)에서 문자열이어야합니다. 두 경우 모두 (IL) s.Length에서 (인스턴스) string.Length속성 을 의미합니다 .

dynamicA는 매우 다른 짐승; 와 가장 유사 object하지만 동적 디스패치가 있습니다.

dynamic s = "abc";
Console.WriteLine(s.Length);

여기에 dynamics 으로 입력 됩니다 . 그것에 대해 알지 못한다 string.Length는 모르기 때문에, 아무것도 에 대한 s컴파일 타임에 있습니다. 예를 들어 다음은 컴파일되지만 실행되지는 않습니다.

dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);

런타임 (전용), 그것은 것입니다 확인 에 대한 FlibbleBananaSnowball재산 - 그것을 찾기 위해 실패, 그리고 불꽃의 샤워에서 폭발.

을 사용 dynamic하면 속성 / 메소드 / 연산자 / 등이 실제 객체를 기반으로 런타임에 해결 됩니다 . COM (런타임 전용 속성을 가질 수 있음), DLR 또는와 같은 다른 동적 시스템과 대화 할 때 매우 편리합니다 javascript.


3
정적으로 선언 된 클래스의 동적 조상이 있다면 흥미로운 질문이 될 것입니다. 예 : 클래스 X {public int Y {get; set;}} dynamic (X) s = GetSpecialX (); 호출 문자열 테스트 = sY; 컴파일러는 Y에 대해 알고 있지만 문자열 test2 = sZ는 정상적으로 컴파일되고 런타임에 확인되므로 컴파일러 오류가 발생합니다. 그런 반동적 클래스의 많은 가치를 생각할 수 있습니다!
mmmmmmmm 2016 년

@rstevens-IIRC, 인터페이스를 통해 동적 동작을 추가 할 수 있습니다 (C #에서 동적 유형을 구현하기위한 직접적인 언어 지원은 없지만 소비 만 가능). 비현실적이지는 않습니다 ... 오 우리가 가질 수있는 재미;- p
Marc Gravell

var하위 유형과 암시 적 캐스트로 인해 바람직하지 않은 유형을 유추 할 수 있다는 점에 유의해야합니다 . 즉, 묵시적 캐스트가 발생할 var때 예상보다 정적으로 다른 유형을 해결했을 수 있습니다 (주로 더 일반적인 유형이지만 이에 국한되지 않음). 일반의 예는 대 대 하지만, 다른 더의 비열한 (사실적인)의 경우가 발생할 수 있습니다 미묘한 버그가 발생할 수 있습니다. object x = ""var x = ""var x = "" as object

Marc의 좋은 예제에 대해 더 자세히 설명하기 위해 (정적 유형의 경우) 컴파일러는 호출 할 과부하가WriteLine 어느 것인지 정확히 알고 있습니다. 이 "바인딩"은 컴파일 타임에 발생합니다. 의 경우에는 dynamic,의 유형 .Length이어야 dynamic도, 그리고 그것은의 (전혀있는 경우) 과부하를 결정 런타임 때까지하지 WriteLine맞는 최고. 바인딩은 런타임에 발생합니다.
Jeppe Stig Nielsen

4
varVisual Studio 에서 키워드 를 가리키면 추론되는 실제 유형이 표시됩니다. 컴파일 타임에 해당 유형이 알려져 있음을 나타냅니다.
Christian Fredh

56

var 로 선언 된 변수 는 내재적이지만 정적으로 유형이 지정됩니다. dynamic 으로 선언 된 변수 는 동적으로 유형이 지정됩니다. 이 기능은 Ruby 및 Python과 같은 동적 언어를 지원하기 위해 CLR에 추가되었습니다.

나는이 수단 것을 추가해야 동적 선언이 실행 시간에 해결이 VAR의 선언은 컴파일 시간에 해결됩니다.


42

dynamicvar의 차이점을 설명하려고합니다 .

dynamic d1;
d1 = 1;
d1 = "http://mycodelogic.com";

작동합니다. 컴파일러는 동적 변수 유형을 다시 만들 수 있습니다 .
먼저 형식을 정수 로 만들고 그 후에 컴파일러는 형식을 문자열 로 다시
만들지 만 var의 경우

var v1;  // Compiler will throw error because we have to initialized at the time of declaration  
var v2 = 1; // Compiler will create v1 as **integer**
v2 = "Suneel Gupta"; // Compiler will throw error because, compiler will not recreate the type of variable 


' var '키워드를 사용하는 경우 컴파일 타임에 컴파일러에서 유형이 결정되는 반면 ' dynamic '키워드를 사용하는 경우 런타임에 의해 유형이 결정됩니다.
' var '키워드는 컴파일러가 초기화 표현식에서 유형을 판별 할 수있는 암시 적으로 유형이 지정된 로컬 변수입니다. LINQ 프로그래밍을 수행 할 때 매우 유용합니다.
컴파일러에는 동적 유형의 변수 에 대한 정보가 없습니다 . 따라서 컴파일러는 지능을 보여주지 않습니다.
컴파일러에는 var 유형 의 저장된 값에 대한 모든 정보가 있으므로 컴파일러는 지능을 보여줍니다.
동적 유형은 함수 인수로 전달 될 수 있고 함수는 객체 유형을 리턴 할 수
있지만
var 유형은 함수 인수로 전달 될 수 없으며 함수는 오브젝트 유형을 리턴 할 수 없습니다. 이 유형의 변수는 정의 된 범위에서 작동 할 수 있습니다.


14

var는 정적 형식 검사 (초기 바인딩)가 적용되었음을 나타냅니다. dynamic은 동적 유형 검사 (후기 바인딩)가 적용됨을 의미합니다. 코드 측면에서 다음을 고려하십시오.

class Junk
{
    public void Hello()
    {
        Console.WriteLine("Hello");
    }
}

class Program
{
    static void Main(String[] args)
    {
        var a = new Junk();
        dynamic b = new Junk();

        a.Hello();

        b.Hello();
    }
}

이것을 컴파일하고 ILSpy로 결과를 검사하면 컴파일러가 b에서 Hello ()에 대한 호출을 처리하는 늦은 바인딩 코드를 추가 한 반면 초기 바인딩이 a에 적용되었으므로 a는 Hello를 호출 할 수 있음을 알 수 있습니다 () 직접.

예 (ILSpy 분해)

using System;
namespace ConsoleApplication1
{
    internal class Junk
    {
        public void Hello()
        {
            Console.WriteLine("Hello");
        }
    }
}

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication1
{
    internal class Program
    {
        [CompilerGenerated]
        private static class <Main>o__SiteContainer0
        {
            public static CallSite<Action<CallSite, object>> <>p__Site1;
        }
        private static void Main(string[] args)
        {
            Junk a = new Junk();      //NOTE: Compiler converted var to Junk
            object b = new Junk();    //NOTE: Compiler converted dynamic to object
            a.Hello();  //Already Junk so just call the method.

                          //NOTE: Runtime binding (late binding) implementation added by compiler.
            if (Program.<Main>o__SiteContainer0.<>p__Site1 == null)
            {
                Program.<Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "Hello", null, typeof(Program), new CSharpArgumentInfo[]
                {
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                }));
            }
            Program.<Main>o__SiteContainer0.<>p__Site1.Target(Program.<Main>o__SiteContainer0.<>p__Site1, b);
        }
    }
}

차이점을 발견하기 위해 할 수있는 최선의 방법은 이와 같은 작은 콘솔 앱을 작성하고 ILSpy로 직접 테스트하는 것입니다.


IL이 컴파일 후 두 가지를 모두 처리하는 방법에 대한 훌륭한 기본 예. 감사.
Kings

12

한 가지 큰 차이점-동적 반환 유형을 가질 수 있습니다.

dynamic Foo(int x)
{
    dynamic result;

    if (x < 5)
      result = x;
    else
      result = x.ToString();

    return result;
}

10

다음은 Dynamic (4.0)과 Var의 차이점을 보여주는 간단한 예입니다.

dynamic  di = 20;
dynamic ds = "sadlfk";
var vi = 10;
var vsTemp= "sdklf";

Console.WriteLine(di.GetType().ToString());          //Prints System.Int32
Console.WriteLine(ds.GetType().ToString());          //Prints System.String
Console.WriteLine(vi.GetType().ToString());          //Prints System.Int32
Console.WriteLine(vsTemp.GetType().ToString());      //Prints System.String

**ds = 12;**   //ds is treated as string until this stmt now assigning integer.

Console.WriteLine(ds.GetType().ToString());          **//Prints System.Int32**

**vs = 12**; //*Gives compile time error* - Here is the difference between Var and Dynamic. var is compile time bound variable.

시바 마 미디


2
**코드 예제에서 문자 가 존재한다는 것은 강조만을 나타 내기위한 것이며 실제 작업 코드의 일부가 아닙니다.
DavidRR

7

var 컴파일러가 올바른 유형을 추측하도록하는 일반적인 유형 선언의 약어입니다.

dynamic 컴파일러가 아닌 런타임에 모든 검사가 수행되는 새로운 (정적) 유형입니다.


4

var로 선언 된 변수의 유형은 컴파일러에 의해 결정되며, 유형 이름을 지정하는 지름길입니다.

그러나 동적은 런타임에 결정되며 컴파일러는 실제 유형을 모릅니다. 해당 변수를 사용하는 모든 메소드 / 필드 / 속성 액세스는 런타임에 해결됩니다.


3

이것은 실제 데모를 통해 varVS Dynamic에 대해 이야기하는 멋진 YouTube 비디오입니다 .

아래는 스냅 샷에 대한 자세한 설명입니다.

동적은 늦은 바인딩 (동적으로 평가)되는 동안 Var은 초기에 바인딩 (정적으로 검사)됩니다.

Var 키워드는 오른쪽 데이터를 확인한 다음 컴파일 시간 동안 왼쪽 데이터 형식을 결정합니다. 즉, var 키워드는 입력 내용을 많이 저장합니다. 툴팁에서 문자열 데이터를 제공하고 x 변수가 문자열 데이터 유형을 표시 할 때 아래 이미지를 살펴보십시오.

여기에 이미지 설명을 입력하십시오

반면에 동적 키워드는 완전히 다른 목적을위한 것입니다. 동적 객체는 런타임 중에 평가됩니다. 예를 들어 아래 코드에서 "Length"속성이 존재하는지 여부는 런타임 동안 평가됩니다. 의도적으로 작은 "l"을 입력 했으므로이 프로그램은 정상적으로 컴파일되었지만 실제로 실행될 때 "length"속성이있을 때 오류가 발생했습니다. (작은 "l")이라고합니다.

여기에 이미지 설명을 입력하십시오


2

동적 변수 및 var 변수는 모든 유형의 값을 저장할 수 있지만 선언시 'var'을 초기화하는 데 필요합니다.

컴파일러에는 '동적'변수 유형에 대한 정보가 없습니다. var는 컴파일러에 안전합니다. 즉, 컴파일러에는 저장된 값에 대한 모든 정보가 있으므로 런타임시 아무런 문제가 발생하지 않습니다.

동적 유형은 함수 인수로 전달 될 수 있으며 함수도이를 리턴 할 수 있습니다. Var 형식은 함수 인수로 전달할 수 없으며 함수는 개체 형식을 반환 할 수 없습니다. 이 유형의 변수는 정의 된 범위에서 작동 할 수 있습니다.

동적 캐스팅의 경우에는 필요하지 않지만 stored type과 관련된 속성 및 메서드를 알아야합니다. var의 경우 컴파일러에서 작업을 수행하기위한 모든 정보가 있으므로 캐스팅 할 필요가 없습니다.

dynamic : 리플렉션 또는 동적 언어 지원 또는 COM 객체를 사용하여 코딩 할 때 더 적은 양의 코드를 작성해야하므로 유용합니다.

var : linq 쿼리에서 결과를 가져올 때 유용합니다. 3.5 프레임 워크에서는 linq 기능을 지원하기 위해 소개합니다.

참조 : 카운셀링


2
  1. Var 및 동적 정의 유형
  2. 동적은 런타임에 컴파일 타임에 var.
  3. var 선언과 초기화에서 둘 다 상수 변수와 같이 필수입니다.
  4. 동적 초기화에서 읽기 전용 변수와 같은 런타임에있을 수 있습니다.
  5. var type에서 초기화시 결정된 유형은 다음에 변경할 수 없지만
  6. dynamic은 사용자 정의 데이터 유형도 모든 유형을 채택 할 수 있습니다.

1

dynamic과 var를 혼동하지 마십시오. var를 사용하여 지역 변수를 선언하는 것은 컴파일러가 표현식에서 특정 데이터 유형을 유추하는 구문 단축키 일뿐입니다. var 키워드는 메서드 내에서 로컬 변수를 선언하는 데만 사용할 수 있으며 동적 키워드는 로컬 변수, 필드 및 인수에 사용할 수 있습니다. 표현식을 var로 캐스트 할 수 없지만 표현식을 동적으로 캐스트 할 수 있습니다. dynamic으로 선언 된 변수를 초기화 할 필요는 없지만 var를 사용하여 선언 된 변수를 명시 적으로 초기화해야합니다.


1
  1. Var (Implicit typed local variable) 키워드는 로컬 변수를 정의하는 데 사용됩니다 .Var의 경우 기본 데이터 형식은 초기 할당을 기반으로 컴파일 타임 자체에서 결정됩니다. Var 형식과 호환되지 않는 값을 저장하려고하면 컴파일 시간 오류가 발생합니다.

예:

Var strNameList=new List<string>(); By using this statement we can store list of names in the string format. 
strNameList.add("Senthil");
strNameList.add("Vignesh");

strNameList.add(45); // This statement will cause the compile time error.

그러나 동적 형식에서는 기본 형식이 런타임에만 결정됩니다. 동적 데이터 형식은 컴파일 타임에 확인되지 않고 강력하게 형식화되지 않습니다. 동적 형식에 대한 초기 값을 할당 한 다음 새로운 형식으로 다시 할당 할 수 있습니다 수명 기간 동안의 가치.

예:

dynamic test="Senthil";
Console.Writeline(test.GetType())  // System.String

test=1222;
Console.Writeline(test.GetType())  // System.Int32

test=new List<string>();
Console.Writeline(test.GetType())  //System.Collections.Generic.List'1[System.String]

또한 linli를 사용하여 작업 할 때 더 나은 지원을 제공하지 않으며 람다 식, 확장 메서드 및 익명 메서드를 지원하지 않기 때문에 IntelliSense 지원도 제공하지 않습니다.


1

차이점은 다음과 같습니다.

  • var는 정적으로 유형이 지정되고 (컴파일 시간) 동적이 동적으로 유형이 지정됩니다 (런타임)

  • var로 선언 된 변수는 로컬에서만 사용할 수 있고 동적 변수는 매개 변수로 함수에 전달 될 수 있습니다 (함수 서명은 매개 변수를 var가 아닌 동적으로 정의 할 수 있음).

  • 동적으로 속성의 분석은 런타임에 발생하며 var의 경우 컴파일 시간에 동적으로 선언 된 모든 변수가 존재하거나 존재하지 않을 수있는 메소드를 호출 할 수 있으므로 컴파일러는 오류를 발생시키지 않습니다.

  • var는 불가능하지만 동적으로는 가능합니다 (객체는 var가 아니라 동적으로 캐스팅 할 수 있음).

아룬 비자이라 하반

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