2012-11-25 4 views
5

반사경에서 + 연산자를 Delegate 또는 MulticastDelegate 아래 찾을 수 없습니다.왜 Delegate.Combine을 사용하려면 캐스트가 필요하지만 + 연산자는 사용하지 않습니까?

나는 이것이 캐스트 필요가없는 방법을 알아 내려고 노력 해요 :

Action a =() => Console.WriteLine("A"); 
Action b =() => Console.WriteLine("B"); 

Action c = a + b; 

을하지만 이것은 수행합니다

Action a =() => Console.WriteLine("A"); 
Action b =() => Console.WriteLine("B"); 

Action c = (Action)MulticastDelegate.Combine(a, b); 

을 첫 번째 샘플에서는 내부적으로 수행 캐스트입니다 ? 이 캐스트가 필요하지 않도록

답변

1

다음의 예 촬영

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     Program.Test1(); 
     Program.Test2(); 
    } 
    public static void Test1() 
    { 
     Action a = delegate 
     { 
      Console.WriteLine("A"); 
     }; 
     Action b = delegate 
     { 
      Console.WriteLine("B"); 
     }; 
     Action c = (Action)Delegate.Combine(a, b); 
     c(); 
    } 
    public static void Test2() 
    { 
     Action a = delegate 
     { 
      Console.WriteLine("A"); 
     }; 
     Action b = delegate 
     { 
      Console.WriteLine("B"); 
     }; 
     Action c = (Action)Delegate.Combine(a, b); 
     c(); 
    } 
} 

것은 그들은 단지 C#을 첫 번째 테스트에서 몇 가지 문법 설탕을 제공하고, 똑같은 일을 할 것 같다 .

4

+=-=가 언어 수준에서 구현되는 알려진 위임 유형 (컴파일러의 도움으로 예), Delegate.Combine 반면, Delegate 반환 형식을 가진 평범한 (제네릭이 아닌) 방법 그래서 캐스팅이 필요합니다.

1

첫 번째 샘플에는 덮개 아래에서 수행 한 캐스트가 있습니까?

예, 말할 수 있습니다!

Combine 메서드는 .NET C#이없는 .NET 1로 작성되었습니다. Combine의 공식적인 반환 형식 그러므로 Delegate해야했다 : 모두 abAction을 때

public static Delegate Combine(Delegate a, Delegate b) 
{ 
    ... 
} 

그러나이 방법은 여전히 ​​Action를 반환합니다. 그리고 예, ab은 동일한 런타임 유형을 가져야합니다. Combine

작성하지 마십시오 MulticastDelegate.CombineSystem.Delegate 클래스에 의해 정의 된 static 방법이다. 그러므로 Delegate.Combine라고하면 덜 혼란 스럽습니다.

우회 :

C 번호의 현재 버전과 Combine이 contravariant 대표 유형 문제가있다. 지금

Action<string> doSomethingToString; // will be assigned below 

Action<ICloneable> a = cloneable => { Console.WriteLine("I'm cloning"); cloneable.Clone(); } 
Action<IConvertible> b = convertible => { Console.WriteLine("I'm converting"); convertible.ToInt32(CultureInfo.InvariantCulture); } 

Action<string> aStr = a; // OK by contravariance of Action<in T>, aStr and a reference same object 
Action<string> bStr = b; // OK by contravariance of Action<in T>, bStr and b reference same object 

doSomethingToString = aStr + bStr; // throws exception 
doSomethingToString("42");   // should first clone "42" then convert "42" to Int32 

가정 프레임 워크의 일부 미래 버전은 일반적인 Combine 방법 소개 : 다음 사항을 고려

public static TDel Combine<TDel>(TDel a, TDel b) where TDel : Delegate 
{ 
    // use typeof(TDel) to figure out type of new "sum" delegate 
} 

+ 새로운 제네릭에 대한 호출로 번역되었다 C 번호는 변경되었습니다 가정 Combine<> 메서드이면 반항 및 위임 조합이 수정 될 것입니다! 나는 그들이 더 높은 우선 순위를 가지고 있다고 말하지만 여전히 그렇다고 생각한다.

class Program 
{ 
    static void Main(string[] args) 
    { 
     Test1(); 
     Test2(); 
    } 

    public static void Test1() 
    { 
     Action a =() => Console.WriteLine("A"); 
     Action b =() => Console.WriteLine("B"); 

     Action c = a + b; 
     c(); 
    } 

    public static void Test2() 
    { 
     Action a =() => Console.WriteLine("A"); 
     Action b =() => Console.WriteLine("B"); 

     Action c = (Action)MulticastDelegate.Combine(a, b); 
     c(); 
    } 
} 

그런 다음 ILSpy으로보고 :

+1

이 같은 뭔가를해야만 수행 가정 각 대리자 형식은 자신의 정적'Combine' 방법을 정의하는 어떤 근본적인 문제가있을 것인가? 그런 다음 두 대표자 'X'와 'Y'가 둘 다 'FooDelegate'로 대체 할 수있는 두 유형 인 경우 'FooDelegate.Combine (X, Y)'를 사용할 수 있습니다. 공분산 문제가 없더라도'(FooDelegate) Delegate.Combine (X, Y)'보다 깔끔하게 보일 수 있으며 'X'와 'Y'가 적합하다는 컴파일 타임 검사를 추가 할 수 있습니다. – supercat

+0

@supercat 나에게 그것은 좋은 해결책처럼 들린다. –

0

"연산자 오버로딩"을 사용하여 완료되었으므로 자신의 개체에서도이 작업을 수행 할 수 있습니다.

public class MyObject 
{ 
    public string Property { get; set; } 

    public MyObject(string property) 
    { 
     this.Property = property; 
    } 

    public static MyObject operator +(MyObject a1, MyObject a2) 
    { 
     return new MyObject(a1.Property + a2.Property); 
    } 
} 

    MyObject o1 = new MyObject("Hello"); 
    MyObject o2 = new MyObject(" World!"); 

    MyObject o3 = o1 + o2; 

결과 : o3.Property = "Hello World!" 그래서

나는 framwork이 배경

public static Action operator +(Action a1, Action a2) 
    { 
     return (Action)MulticastDelegate.Combine(a1,a2); 
    } 
+0

Oh 예 오퍼레이터 오버로드에 대해 알고 있습니다. Reflactor에서이 연산자를 찾을 수 없었으며 어떻게 처리했는지 궁금합니다. –

관련 문제