런타임에서 타입 변환이 가능한 Dynamic 형식



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        static void Main(string[] args)
        {
 
            //컴파일 타임에 결정
            var s = "ddd";
 
            //런타임에 데이터 타입이 결정됨
            dynamic dd = 3;
 
            //런타임 중간에 다른 타입으로 변경 가능
            dd = "ddd";
            Console.WriteLine(dd);
 
 
            dd = 10;
 
            //컴파일 타임에 에러가 발생하진 않지만 런타임에서 예외를 발생시킨다
            //Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: '암시적으로 'int' 형식을 'string' 형식으로 변환할 수 없습니다.'
            s = dd;
 
            
        }

cs




dynamic 형식 사용

C# 4에서는 새로운 형식 dynamic을 소개합니다. 이 형식은 정적 형식이지만 dynamic 형식의 개체가 정적 형식 검사를 건너뜁니다.대부분의 경우 이 형식은 object 형식을 가지고 있는 것처럼 작동합니다. 컴파일 시간에 dynamic 형식의 요소는 모든 연산을 지원하는 것으로 간주됩니다. 따라서 개체가 값을 COM API, IronPython 같은 동적 언어, HTML DOM(문서 개체 모델), 리플렉션 또는 프로그램의 다른 곳 등 어디서 가져오든 신경을 쓸 필요가 없습니다. 그러나 코드가 유효하지 않으면 런타임 시 오류가 catch됩니다.

예를 들어 다음 코드의 인스턴스 메서드 exampleMethod1에 매개 변수가 하나뿐인 경우, 컴파일러는 메서드 ec.exampleMethod1(10, 4)에 대한 첫 번째 호출이 유효하지 않음을 인식합니다. 여기에 인수가 두 개 포함되었기 때문입니다. 호출 시 컴파일러 오류가 발생합니다. 컴파일러는 메서드 dynamic_ec.exampleMethod1(10, 4)에 대한 두 번째 호출을 확인하지 않습니다. dynamic_ec의 형식이 dynamic이기 때문입니다. 따라서 컴파일러 오류가 보고되지 않습니다. 그러나 이 오류는 알림을 무기한 이스케이프하지 않고, 런타임에 catch되며 런타임 예외를 일으킵니다.


static void Main(string[] args)
{
    ExampleClass ec = new ExampleClass();
    // The following call to exampleMethod1 causes a compiler error 
    // if exampleMethod1 has only one parameter. Uncomment the line
    // to see the error.
    //ec.exampleMethod1(10, 4);

    dynamic dynamic_ec = new ExampleClass();
    // The following line is not identified as an error by the
    // compiler, but it causes a run-time exception.
    dynamic_ec.exampleMethod1(10, 4);

    // The following calls also do not cause compiler errors, whether 
    // appropriate methods exist or not.
    dynamic_ec.someMethod("some argument", 7, null);
    dynamic_ec.nonexistentMethod();}
class ExampleClass
{
    public ExampleClass() { }
    public ExampleClass(int v) { }

    public void exampleMethod1(int i) { }

    public void exampleMethod2(string str) { }
}

이 예제에서 컴파일러의 역할은 dynamic으로 형식이 지정된 개체 또는 식에 대해 각 문이 해야 할 일에 대한 정보를 패키지하는 것입니다. 런타임에는 저장된 정보의 검사가 수행되며, 유효하지 않은 문에서 런타임 예외가 발생합니다.

대부분의 동적 작업은 결과 그 자체가 dynamic입니다. 다음 예제에서 testSum이 사용된 곳에 마우스 포인터를 올려두면 IntelliSense에서 (지역 변수) dynamic testSum 형식을 표시합니다.


dynamic d = 1;
var testSum = d + 3;
// Rest the mouse pointer over testSum in the following statement.
System.Console.WriteLine(testSum);

결과가 dynamic이 아닌 작업은 다음을 포함합니다.

  • dynamic에서 다른 형식으로의 전환.
  • dynamic 형식의 인수를 포함하는 생성자 호출.

예를 들어 다음 선언에서 testInstance의 형식은 dynamic이 아니라 ExampleClass입니다.


var testInstance = new ExampleClass(d);

변환 예제는 다음 섹션인 "변환"에 나와 있습니다.

변환

동적 개체와 다른 형식 간에 손쉽게 변환할 수 있습니다. 따라서 개발자는 동적 동작과 비동적 동작 간에 전환할 수 있습니다.

다음 예제와 같이 개체를 동적 형식으로 암시적으로 변환할 수 있습니다.


dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

반대로, 암시적 변환을 dynamic 형식의 식에 동적으로 적용할 수 있습니다.

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;

동적 형식의 인수로 오버로드 확인

메서드 호출 내 하나 이상의 인수에 dynamic 형식이 있거나 메서드 호출의 수신자가 dynamic 형식인 경우 오버로드 확인은 컴파일 시간이 아니라 런타임에 발생합니다. 다음 예제에서 액세스 가능한 유일한 exampleMethod2 메서드가 문자열 인수를 사용하도록 정의되는 경우, d1을 인수로서 전송하면 컴파일러 오류는 발생하지 않지만 런타임 예외가 발생합니다. d1의 런타임 형식은 int인데 exampleMethod2에는 문자열이 필요하므로 오버로드 확인이 런타임에 실패합니다.


// Valid.
ec.exampleMethod2("a string");

// The following statement does not cause a compiler error, even though ec is not
// dynamic. A run-time exception is raised because the run-time type of d1 is int.
ec.exampleMethod2(d1);
// The following statement does cause a compiler error.
//ec.exampleMethod2(7);

동적 언어 런타임

DLR(동적 언어 런타임)은 .NET Framework 4의 새로운 API입니다. DLR은 C#에서 dynamic 형식을 지원하는 인프라를 제공하며, IronPython 및 IronRuby와 같은 동적 프로그래밍 언어를 구현합니다. DLR에 대한 자세한 내용은 동적 언어 런타임 개요를 참조하세요.

COM Interop

C# 4에는 Office 자동화 API와 같은 COM API와의 상호 운용 환경을 개선하는 몇 가지 기능이 포함되어 있습니다. 개선 사항 중에는 dynamic 형식의 사용 및 명명된 인수 및 선택적 인수의 사용이 포함됩니다.

많은 COM 메서드는 형식을 object로 지정하여 인수 형식 및 반환 형식의 변환을 허용합니다. C#에서는 강력한 형식의 변수로 조정하기 위해 값을 명시적으로 캐스팅해야 했습니다. /link(C# 컴파일러 옵션) 옵션을 사용하여 컴파일하는 경우 dynamic 형식을 사용하면 COM 서명에서 object의 발생을 마치 dynamic 형식인 것처럼 취급하여 캐스팅을 상당 부분 피할 수 있습니다. 예를 들어 다음 문은 dynamic 형식은 있고 dynamic 형식은 없는 Microsoft Office Excel 스프레드시트의 셀에 액세스하는 방법과 대조됩니다.


// Before the introduction of dynamic.
((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name";
Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];




// After the introduction of dynamic, the access to the Value property and
// the conversion to Excel.Range are handled by the run-time COM binder.
excelApp.Cells[1, 1].Value = "Name";
Excel.Range range2010 = excelApp.Cells[1, 1];




ref : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/types/using-type-dynamic




+ Recent posts