잊지 않겠습니다.

1. Dynamic Lookup

.NET Framework 2009. 1. 7. 12:56


method나 instance를 동적으로 가능하도록 변경.

COM, IronPython, HTML DOM 또는 Reflection을 통해 얻어진 객체에 대한 동적인 접근이 가능.

 

The Dynamic Type

C# 4.0에서는 "dynamic" 으로 지정된 Type의 경우에는 runtime 시에 객체의 Byte code를 생성하게 된다.

 

  1. dynamic d = GetDynamicObject(....);  
  2. d.M(7)  

C# compiler에서 Compile시에 dynamic으로 지정된 Instance의 경우에는 Compile시에 넘어가게 되고, runtime시에 method를 각 parameter의 type에 따라서 구현, 실행하게 된다. 

이는 Type에서만 구현되는 것이 아닌, Method, Property 에서도 역시 같이 구현되게 된다.

 

: 상당히 멋진 기능이라고 생각되긴 하는데.. C#이 가진 선언적 언어 특성을 많이 버리는 느낌이 든다. 일단 백서에도 나와있듯이 안정성과 속도를 조금은 버리는 작업이기 때문에 사용하는 것에 있어서 많은 생각을 해봐야지 될것 같다. 무엇보다 Python이 아닌 IronPython의 객체를 얻어오는 것이라서, MS 가 아닌 다른 언어의 객체에 대한 구현은 조금 후에 알아봐야지 될것 같다. (분명히 Python도 되게 하는 방법이 생길것이다.)

 

: 그리고, 이미 사용되고 있는 곳은 매우 많다. Reflection을 통한 invoke와 너무나도 유사한 기능으로 Reflection의 확장으로 보이는 것은 나만의 착각인것일까? 

 

: 생각하지 못했던 내용이 있었다. JSON 데이터 포멧의 경우에는 자유롭게 확장들이 가능해진다. 사용되는 Class의 Property가 무엇인지만 알면 dynamic으로 선언해서 데이터를 얻어오고, 데이터에 대한 객체화가 매우 자유롭게 바뀌게 된다. 

  1. string jsonText = "{ xyz: 123, items: [ 10, 100, 1000 ] }";  
  2.   
  3. JsonReader jsonReader = new JsonReader(jsonText);  
  4. dynamic jsonObject = jsonReader.ReadValue();  
  5.   
  6. dynamic items = jsonObject.items;  
  7. items.Item(2, 1001);  
  8.   
  9. dynamic bar = new JsonObject();  
  10. bar.name = "c#";  
  11. jsonObject.bar = bar;  
  12.   
  13. JsonWriter writer = new JsonWriter();  
  14. writer.WriteValue((object)jsonObject);  
  15.   
  16. string newJsonText = writer.Json;  

 


Runtime Lookup

1. COM objects

: IDispatch를 통한 COM object의 이용. 

2. Dynamic objects

: IDynamicObject interface를 상속한 Class 

3. Plain objects 

: Standard .NET Object

위의 3가지 경우에서 Runtime lookup을 사용가능하다.  

 

  1. dynamic d1 = new Foo();  
  2. dynamic d2 = new Bar();  
  3. string s;  
  4.   
  5. d1.M(s, d2, 3, null);  

 

The Dynamic Langauage Runtime(DLR)

New API in .NET 4.0: DLR은 C#만이 아닌 .NET 기반의 다른 언어들에 대한 변환을 제공 

 

Open Issues

  • Extendted Method에 대한 지원을 할 수 없다. Dynamic으로 선언된 Instance에 대한 Extented Method를 구현하는 것은 불가능하다.
  • Anonymous functions은 dynamic method call에서 지원할 수 없다. 아래와 같은 코드는 사용 불가능하다.
  1. dynamic collection = ....;  
  2. var result = collection.Select(e=>e+5); //사용 불가능하다.  

 

 

Posted by Y2K
,

Visual Studio 2010과 더불어서 같이 준비중인 C# 4.0에서의 새로운 기능들을 간단히 알아보려고 생각중. 

참고 자료 사이트는

http://code.msdn.microsoft.com/csharpfuture


기본 테마

C# 4.0은 Dynamic programming을 기본 Theme로 가지고 있다.

Dynamic Programming언어라고 할 수 있는 Python이나 Ruby정도까지는 아니지만, Compile 할때가 아닌 Runtime시에 자신의 type을 결정할 수 있는 방법으로 구현되고자 한다.  이러한 Dynamic의 예는 다음과 같은 수 있다. 

1. Python이나 Ruby와 같은 Dynamic Programming language에서 생성된 object

2. IDispatch를 통해 구현된 COM objects

3. refrection을 통해 구현된 .NET framework의 객체들

4. 구조체가 변경된 object. (HTML DOM object)

    

C# 4.0의 주요한 기능은 다음과 같다.

1. Dynamic lookup

:  C#의 runtime시에 object의 type이 결정되게 된다.

2. Named and optional parameters

: C#에서의 각 parameter들은 각각의 기본값을 가질수 있다.

  ( C++에서의 기능과 동일하게 생각하면 된다. 왜 이제서야 구현이 되었는지 모르겠는 아주 편한 기능. 이 기능 하나로 많은 overload를 없애는 것이 가능하다.)

: C#에서의 각 parameter들은 각각의 이름을 가지고 값의 입력이 가능하다.

  ( python이나 javascript에서 간간히 나오는 dictionary 입력과 비슷한 함수의 호출이 가능하다. ) 

3. COM specific interop feature

: .NET Framework에서의 COM object의 interop의 개선 및 향상 

4. Variance 

: IEnumerable의 Interface 변경이 이루어졌다. (이건 좀 큰문제가 발생할 수 도 있을것 같은 생각이 든다. List<object> 등 IEnumerable의 Interface는 너무나 많은 곳에서 사용되고 있는데.. 이 부분은 어찌 해결이 될지..;)



Posted by Y2K
,

Visual Studio 2008에서는 Targeting을 정해줄 수 있다 : .NET Framework의 종류를 지정해서 compile을 시킬 수 있다.

1. Auto-implemented property

  • Property에서 간단히 값을 저장하는 형식이라면 private 변수들을 선언하거나 property의 구현을 하지 않더라도, 구현이 가능하다.
  • Code가 매우 간단해지고, 간단한 수행에서의 가독성을 높여준다.
  • 기존의 get/set에서의 특별한 행동을 해주는 경우에는 전과 같이 안의 코드를 만들어줘야지 된다.        
    class AutoImplementedClass
    {
        public string Name
        {
            get; set;
        }
        public string Customer
        {
            get;
            private set;
        }
    }

  

2. Object / Collection Initializer

  • Class의 선언과 동시에 private 변수를 초기화 시키는 것이 가능하다.
  • Object / Collection Initialize에서는 {}를 사용하는 것을 유념할것.
  • Public 변수들만 된다.    
    List<int> powers = new List<int>{ 1, 2, 3, 4, 5, 6, 7 };    
    class Point
    {
        public int x, y;        
    }
    Point point = new Point{x = 0, y = 1};

  

3. Local Variable Type Inference

  • Type 명을 적지 않더라도, compiler에서 선언 대치해줄수 있다.
  • 'var' keyword를 이용해서 사용가능하다.
  • 주의할 점은 var에서 type을 변화시킬 수 없는 경우에서는 에러가 나타난다.
  • Type이 동적으로 되는 것이 아니라, 초기화 될때 Type은 결정되어 고정된다.

  

4. Anonymous Type

  • 익명 Type Class
  • 프로그램에서 참조할 수 없다.
  • 복잡한 임시 테이블에 사용하는 것이 좋다. 
    static void Main(string[] args)
    {
        var x = new {a =3 , b = 5, c ="some text"}
        assert.AreEqual(3, x.a)
        assert.AreEqual(5, x.b)
        assert.AreEqual("some text", x.c)        
    }

  

5. Lamda Expression

  • Delegate와 매우 연관이 높다.
  • Lamda expression에서 input/output에서 type을 명확히 넣어주고 싶은 경우에는 type을 결정해서 넣어주면 된다.
  • Func<T> : return 값이 존재하는 경우에 기본적으로 사용되는 delegate type (new delegate로 만들어줘도 상관이 없지만, 기왕에 있는 녀석이면 사용하자.)
  • Action<T> : return 값이 존재하지 않는 경우에 사용되는 delegate type (new delegate로 만들어줘도 상관이 없지만, 기왕에 있는 녀석이면 사용하자.)
    SomeDelegate d3 = s => s.ToUpper();
    SomeDelegate d4 = (string s) => {return s.ToUpper()}
    string a = d3("abcde")

  

6. Extension Methods

  • 기존 Class에 새로운 기능을 추가한다.
  • 상속을 받지 않고도 가능하다.
  • 실행 우선 순위가 Instance method보다 낮다.
  • "this string s" 라는 구문으로 string class에 대한 확장 class를 구현 가능하다.
  • 특정한 API를 만드는 것은 좋지만, 가독성에 심각한 문제를 초래할 수도 있다. 
    public static class Extensions
    {
        public static int ToInt32(this string s)    
        {
            return 0;
        }
    }

  

7. Partial Methods

  • Prital Method는 Partial Class안에 선언되어야지 된다.
  • 반드시 Return type은 void가 되어야지 된다.
  • 반드시 private 한정자에서만 가능하다.
  • C++에서의 함수 선언을 header에서 하는 것과 비슷하게 생각하면 쉽다.
  • 구현부가 없는 경우에는 compiler가 연관된 모든 code를 삭제할 수 있다.

  

8. Query Expressions [LINQ]

  • var = contacts = from c in customers where c.City == "London" SELECT new {c.Customer.ID, c.City}
  • Where 문을 Extension Method를 이용해서 만들어주고, Lamda Expression을 이용해서 내부적으로 code를 작성시켜주게 된다.
    class Customer
    {
        public string CustomerID { get; set; }
        public string ContactName { get; set; }
        public string City { get; set; }
    }
    public class Program
    {
        static void Main(string[] args)
        {
            List<Customers> customers = LoadCustomers();
            var query = from c in customers
                                where c.City == "London"
                                select (new {c.CustomerID, c.ContactName} );
            foreach (var item in query)
            {
                Console.WriteLine(item);
            }                
        }
    }

../C# 3.0/LINQ.png

Posted by Y2K
,