programing

C# 4.0의 '다이나믹' 유형은 무엇에 사용됩니까?

javajsp 2023. 5. 29. 09:43

C# 4.0의 '다이나믹' 유형은 무엇에 사용됩니까?

C# 4.0은 '다이나믹'이라는 새로운 유형을 도입했습니다.모든 것이 좋은 것 같지만, 프로그래머는 그것을 무엇에 사용할까요?

그것이 하루를 구할 수 있는 상황이 있습니까?

dynamic키워드가 C# 4.0의 다른 많은 새로운 기능과 함께 추가되어 API가 다른 다른 런타임에 있거나 다른 런타임에서 온 코드와 더 쉽게 대화할 수 있게 되었습니다.

예를 들어 보겠습니다.

COM 개가있경, 예들다니옵우어는.Word.Application오브젝트 및 문서를 열려는 방법에는 15개 이상의 매개 변수가 있으며, 대부분은 선택적입니다.

이 메소드를 호출하려면 다음과 같은 것이 필요합니다(간단하게 설명하자면, 이것은 실제 코드가 아닙니다).

object missing = System.Reflection.Missing.Value;
object fileName = "C:\\test.docx";
object readOnly = true;
wordApplication.Documents.Open(ref fileName, ref missing, ref readOnly,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing);

그 모든 주장들을 주목하세요?4.0 이전 버전의 C#에는 선택적 인수 개념이 없었기 때문에 이를 전달해야 합니다.C# 4.0에서 COM API는 다음과 같은 기능을 도입함으로써 작업이 더 쉬워졌습니다.

  1. 선택적 인수
  2. ref APIsCOM API의 입니다.
  3. 명명된 인수

위의 호출에 대한 새로운 구문은 다음과 같습니다.

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

얼마나 쉬워 보이는지, 얼마나 더 읽기 쉬워지는지 보세요?

그것을 분리해 보겠습니다.

                                    named argument, can skip the rest
                                                   |
                                                   v
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
                                 ^                         ^
                                 |                         |
                               notice no ref keyword, can pass
                               actual parameter values instead

마법은 이제 C# 컴파일러가 필요한 코드를 주입하고 런타임에서 새로운 클래스와 함께 작동하여 이전에 했던 것과 거의 동일한 작업을 수행하지만 구문은 숨겨졌습니다. 이제는 방법에 집중하지 않고 무엇에 집중할 수 있습니다.앤더스 헤일스버그는 다양한 "환상"을 불러와야 한다고 말하는 것을 좋아합니다. 이는 전체의 마법에 대한 일종의 말장난입니다. 일반적으로 특정 유형의 주문을 진행하려면 손을 흔들고 몇 가지 마법 단어를 올바른 순서로 말해야 합니다.COM 객체와 대화하는 예전 API 방식은 많은 것이었습니다. 컴파일러가 코드를 컴파일하도록 유도하기 위해서는 많은 후프를 건너뛰어야 했습니다.

0 이전의이 더 .IDispatch언급.

, 뭔모면다른지그게,▁if면다모른▁you뭔지▁what▁don▁is.IDispatch기본적으로 COM 개체에 대한 반사입니다.와 함께IDispatch는 "알려진 값을 한 후 으로 " 페이스저으게 " 장터로알 " 려인진에 " 서가드 ID 한지무인고묻 " 엇호인수값 " 을는하포함정특형유수있호의배다다할니습출음을열을로마구으막지후축한는에번체객메대▁an▁you▁interface▁call▁known▁ask▁method수,있호▁for▁of다▁the다"할▁"▁numberwhat니출습음을▁save▁object로▁the마Invoke에 있는 IDispatch메소드를 호출하는 인터페이스로, 검색할 수 있는 모든 정보를 전달합니다.

위의 저장 방법은 다음과 같을 수 있습니다(이것은 절대로 올바른 코드가 아닙니다).

string[] methodNames = new[] { "Open" };
Guid IID = ...
int methodId = wordApplication.GetIDsOfNames(IID, methodNames, methodNames.Length, lcid, dispid);
SafeArray args = new SafeArray(new[] { fileName, missing, missing, .... });
wordApplication.Invoke(methodId, ... args, ...);

이 모든 것은 문서를 열기 위한 것입니다.

VB는 오래 전에 이러한 대부분을 즉시 사용할 수 있는 옵션 인수와 지원을 가지고 있었기 때문에 이 C# 코드는 다음과 같습니다.

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

기본적으로 표현력 면에서 C#이 VB를 따라잡는 것이지만, COM뿐만 아니라 확장 가능하게 함으로써 올바른 방식으로 수행합니다.물론 이것은 VB.NET 또는 .NET 런타임 위에 구축된 다른 언어에서도 사용할 수 있습니다.

은 다에대자정확수있다습니인에 대한 더 수 .IDispatch위키피디아의 인터페이스: 당신이 그것에 대해 더 읽고 싶다면 ID를 발송합니다.그건 정말 잔인한 것들입니다.

하지만, 만약 당신이 파이썬 객체와 대화하고 싶다면요?COM 객체에 사용되는 API와는 다른 API가 있으며 Python 객체는 본질적으로 동적이기 때문에 호출할 올바른 메서드와 매개 변수 등을 찾기 위해 반사 마법에 의존해야 하지만 Python을 위해 작성된 .NET 리플렉션은 아닙니다. 위의 ID 디스패치 코드와 거의 비슷합니다.

루비는?여전히 다른 API입니다.

자바스크립트?동일한 거래, 그것에 대한 다른 API.

dynamic 키워드는 다음 두 가지로 구성됩니다.

  1. 의 , C# 새로키워드운,dynamic
  2. 개체를 있는 으로, 다한유개형를알있런클방고법는타, 이클는특구 이 한 특정 합니다.dynamic키워드를 사용하면 통화가 필요하고 올바른 방법으로 연결됩니다.API는 문서화되어 있으므로 런타임에서 제공되는 개체가 포함되지 않은 경우 추가할 수 있습니다.

dynamic그러나 키워드는 기존을 대체하기 위한 것이 아닙니다.NET 전용 코드.물론 수 있지만, 그런 이유로 추가된 것은 아닙니다. 그리고 안데르스 헤일스버그가 선두에 있는 C# 프로그래밍 언어의 저자들은 여전히 C#을 강력한 유형의 언어로 간주하고 그 원칙을 희생하지 않을 것이라고 가장 단호하게 주장해왔습니다.

즉, 다음과 같은 코드를 작성할 수 있습니다.

dynamic x = 10;
dynamic y = 3.14;
dynamic z = "test";
dynamic k = true;
dynamic l = x + y * z - k;

컴파일을 하게 되면, 그것은 일종의 마술 같은 형태의 시스템이 아닙니다.

전체적인 목적은 다른 종류의 물체와 더 쉽게 대화할 수 있도록 하는 것이었습니다.

인터넷에는 키워드, 지지자, 반대자, 토론, 고함, 칭찬 등에 대한 많은 자료가 있습니다.

다음 링크로 시작한 다음 더 많은 링크를 검색하는 것이 좋습니다.

dynamic 키워드는 C# 4.0에 새로 추가되었으며 컴파일러에 변수 유형이 변경될 수 있거나 런타임까지 알 수 없음을 알리는 데 사용됩니다.객체를 캐스팅하지 않고도 객체와 상호 작용할 수 있다고 생각합니다.

dynamic cust = GetCustomer();
cust.FirstName = "foo"; // works as expected
cust.Process(); // works as expected
cust.MissingMethod(); // No method found!

고객을 고객 유형으로 캐스팅하거나 선언할 필요가 없습니다.동적으로 선언했기 때문에 런타임이 대신 FirstName 속성을 검색하고 설정합니다.물론 동적 변수를 사용하는 경우 컴파일러 유형 검사를 포기하는 것입니다.이것은 고객에게 전화하는 것을 의미합니다.MissingMethod()는 컴파일되고 런타임까지 실패하지 않습니다.MissingMethod가 Customer 클래스에 정의되지 않았기 때문에 이 작업의 결과는 RuntimeBinderException입니다.

위의 예는 메서드 및 속성을 호출할 때 동적으로 작동하는 방법을 보여줍니다.또 다른 강력한(그리고 잠재적으로 위험한) 기능은 다양한 유형의 데이터에 대해 변수를 재사용할 수 있다는 것입니다.Python, Ruby 및 Perl 프로그래머들은 이를 활용할 수 있는 수백만 가지 방법을 생각해 낼 수 있을 것입니다. 하지만 저는 C#을 너무 오랫동안 사용해 왔기 때문에 "잘못된" 느낌이 듭니다.

dynamic foo = 123;
foo = "bar";

좋습니다. 위와 같은 코드를 자주 작성하지 않을 것입니다.그러나 변수 재사용이 유용하거나 기존 코드의 더러운 부분을 정리할 수 있는 경우가 있습니다.제가 자주 마주치는 한 가지 간단한 경우는 소수점과 두 배 사이에서 끊임없이 캐스팅을 해야 한다는 것입니다.

decimal foo = GetDecimalValue();
foo = foo / 2.5; // Does not compile
foo = Math.Sqrt(foo); // Does not compile
string bar = foo.ToString("c");

2.5는 더블로 입력하고 3은 수학 때문에 컴파일하지 않기 때문에 두 번째 줄은 컴파일하지 않습니다.Sqrt는 두 배를 기대합니다.물론 변수 유형을 캐스팅하거나 변경하기만 하면 되지만 동적으로 사용하는 것이 타당한 상황이 있을 수 있습니다.

dynamic foo = GetDecimalValue(); // still returns a decimal
foo = foo / 2.5; // The runtime takes care of this for us
foo = Math.Sqrt(foo); // Again, the DLR works its magic
string bar = foo.ToString("c");

추가 기능 읽기: http://www.codeproject.com/KB/cs/CSharp4Features.aspx

저는 아무도 다중 파견을 언급하지 않았다는 것에 놀랐습니다.이 문제를 해결하는 일반적인 방법은 방문자 패턴을 통해 수행되며 항상 가능한 것은 아니므로 쌓이게 됩니다.is수표

여기 제가 직접 응용한 실제 사례가 있습니다.수행하는 대신:

public static MapDtoBase CreateDto(ChartItem item)
{
    if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
    if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
    if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
    //other subtypes follow
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

사용자:

public static MapDtoBase CreateDto(ChartItem item)
{
    return CreateDtoImpl(item as dynamic);
}

private static MapDtoBase CreateDtoImpl(ChartItem item)
{
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

private static MapDtoBase CreateDtoImpl(MapPoint item)
{
    return new MapPointDto(item);
}

private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
    return new ElevationDto(item);
}

첫 번째 경우에는ElevationPoint의 하위 클래스입니다.MapPoint그리고 만약 그것이 앞에 놓이지 않았다면. MapPoint절대 도달하지 못할 것입니다.가장 가까운 일치 방법이 호출되므로 동적인 경우에는 그렇지 않습니다.

코드를 통해 짐작할 수 있듯이 ChartItem 개체를 직렬화 가능한 버전으로 변환하는 동안 이 기능이 유용하게 사용되었습니다. 제 제 코드를 .ChartItem유용하지 않은 직렬화 관련 속성을 가진 개체입니다.

정적 유형 언어(CLR)를 DLR(동적 언어 런타임)에서 실행되는 동적 언어(파이톤, 루비...)와 상호 운용하기 쉽게 합니다. MSDN:

예를 들어 다음 코드를 사용하여 C#의 XML에서 카운터를 증분할 수 있습니다.

Scriptobj.SetProperty("Count", ((int)GetProperty("Count")) + 1);

DLR을 사용하면 동일한 작업에 대신 다음 코드를 사용할 수 있습니다.

scriptobj.Count += 1;

MSDN은 다음과 같은 이점을 나열합니다.

  • 동적 언어를 .NET Framework로 이식하는 작업 간소화
  • 정적으로 입력된 언어에서 동적 기능 사용
  • DLR 및 .NET Framework의 향후 이점 제공
  • 라이브러리 및 개체 공유 사용
  • 신속한 동적 디스패치 및 호출 제공

자세한 내용은 MSDN을 참조하십시오.

사용 예:

공통 속성 'CreationDate'를 가진 많은 클래스를 사용합니다.

public class Contact
{
    // some properties

    public DateTime CreationDate { get; set; }        
}

public class Company
{
    // some properties

    public DateTime CreationDate { get; set; }
    
}

public class Opportunity
{
    // some properties

    public DateTime CreationDate { get; set; }
    
}

CreationDate' 속성의 값을 검색하는 일반적인 메서드를 작성하는 경우 다음과 같이 반사를 사용해야 합니다.

static DateTime RetrieveValueOfCreationDate(Object item)
{
    return (DateTime)item.GetType().GetProperty("CreationDate").GetValue(item);
}

동적' 개념을 사용하면 코드가 훨씬 우아해집니다.

static DateTime RetrieveValueOfCreationDate(dynamic item)
{
    return item.CreationDate;
}

COM 인터럽트.특히 저는 잘 모릅니다.그것은 그것을 위해 특별히 설계되었습니다.

의 베스트 dynamic였습니다.NET에서 데이터 액세스 계층을 작성할 때입니다(사용).SQLDataReader코드가 이미 작성된 레거시 저장 프로시저를 호출했습니다.이러한 레거시 저장 프로시저에는 비즈니스 로직의 대부분이 포함되어 있습니다.제 데이터 액세스 계층은 구조화된 데이터를 C# 기반의 비즈니스 로직 계층으로 반환하여 일부 조작을 수행해야 했습니다(거의 없음에도 불구하고).모든 저장 프로시저는 서로 다른 데이터 집합( 열)을 반환합니다.그래서 저는 반환된 데이터를 보관하고 BLL에 전달하기 위해 수십 개의 클래스나 구조체를 만드는 대신, 꽤 우아하고 깔끔한 아래 코드를 작성했습니다.

public static dynamic GetSomeData(ParameterDTO dto)
        {
            dynamic result = null;
            string SPName = "a_legacy_stored_procedure";
            using (SqlConnection connection = new SqlConnection("my connection string"))
            {
                SqlCommand command = new SqlCommand(SPName, connection);
                command.CommandType = System.Data.CommandType.StoredProcedure;                
                command.Parameters.Add(new SqlParameter("@empid", dto.EmpID));
                command.Parameters.Add(new SqlParameter("@deptid", dto.DeptID));
                connection.Open();
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        dynamic row = new ExpandoObject();
                        row.EmpName = reader["EmpFullName"].ToString();
                        row.DeptName = reader["DeptName"].ToString();
                        row.AnotherColumn = reader["AnotherColumn"].ToString();                        
                        result = row;
                    }
                }
            }
            return result;
        }
  1. Pythonnet을 사용하여 CPython과 같은 동적 언어를 호출할 수 있습니다.

dynamic np = Py.Import("numpy")

  1. 에 제네릭을 캐스팅할 수 있습니다.dynamic수치 연산자를 적용할 때.이는 유형 안전을 제공하고 제네릭의 제한을 방지합니다.기본적으로 *덕 타이핑:

T y = x * (dynamic)x서, 디에어typeof(x) is T

사용사의 dynamic타이핑은 공분산 또는 반분산 문제가 발생하는 가상 메소드를 위한 것입니다.그러한 예 중 하나는 악명 높은 것입니다.Clone호출된 개체와 같은 유형의 개체를 반환하는 메서드입니다. 검사를 으로 이 플레인 를▁all▁▁per▁when▁this▁▁the▁ugly▁▁because▁as▁time▁don▁you▁least,▁but▁is▁type▁it▁problem없▁return▁at▁a니es▁bypass▁static▁dynamic다습필는사요할▁with용▁use를스깁▁needt▁not'▁complete▁to정적못ly▁solved긴생항상때object다른 말로 하자면, 출연진들은 암시적이 됩니다.

public class A
{
    // attributes and constructor here
    public virtual dynamic Clone()
    {
        var clone = new A();
        // Do more cloning stuff here
        return clone;
    }
}

public class B : A
{
    // more attributes and constructor here
    public override dynamic Clone()
    {
        var clone = new B();    
        // Do more cloning stuff here
        return clone;
    }
}    

public class Program
{
    public static void Main()
    {
        A a = new A().Clone();  // No cast needed here
        B b = new B().Clone();  // and here
        // do more stuff with a and b
    }
}

런타임에 평가되므로 JavaScript와 같은 유형을 원하는 대로 전환할 수 있습니다.이것은 합법적입니다.

dynamic i = 12;
i = "text";

따라서 필요에 따라 유형을 변경할 수 있습니다.최후의 수단으로 사용하십시오. 유익하지만, 생성된 IL의 측면에서 많은 것이 배후에서 진행되고 있으며 성능 가격이 책정될 수 있다고 들었습니다.

언급URL : https://stackoverflow.com/questions/2690623/what-is-the-dynamic-type-in-c-sharp-4-0-used-for