2012-11-25 29 views
5

Tôi không thể tìm thấy toán tử + trong Trình phản chiếu trong Delegate hoặc MulticastDelegate.Tại sao sử dụng Delegate.Combine yêu cầu dàn diễn viên nhưng sử dụng toán tử + thì không?

Tôi đang cố gắng để tìm ra cách này không cần một dàn diễn viên:

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

Action c = a + b; 

Nhưng điều này không:

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

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

Trong mẫu đầu tiên là diễn viên chỉ thực hiện dưới sự bìa ?

Trả lời

1

Lấy ví dụ sau đây:

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(); 
    } 
} 

Sau đó nhìn vào nó với ILSpy:

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ó vẻ rằng họ làm điều chính xác cùng, chỉ cần C# đang cung cấp một số đường cú pháp trong các thử nghiệm đầu tiên .

4

+=-= được thực hiện ở mức độ ngôn ngữ (ví dụ với trình biên dịch giúp đỡ) với các loại đại biểu được biết đến, vì vậy nó không cần một dàn diễn viên, trong khi Delegate.Combine chỉ là một phương pháp thông thường (không phải chung chung) với Delegate kiểu trả về, vì vậy nó cần một dàn diễn viên.

1

Trong mẫu đầu tiên, dàn diễn viên chỉ được thực hiện dưới vỏ?

Có, bạn có thể nói điều đó!

Phương pháp Combine được viết bằng .NET 1, nơi không tồn tại chung C#. Kiểu trả về chính thức của Combine do đó phải được Delegate:

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

Nhưng phương pháp này vẫn trả về một Action khi cả hai abAction. Và có, ab bắt buộc phải có cùng loại thời gian chạy.

Vui lòng không viết MulticastDelegate.CombineCombine là phương thức static được xác định bởi lớp System.Delegate. Do đó, hãy nói Delegate.Combine, điều đó ít gây nhầm lẫn.

Đường vòng:

Phiên bản hiện tại của C# và Combine có vấn đề với các loại đại biểu contravariant. Hãy xem xét những điều sau đây:

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 

Bây giờ, giả sử một số phiên bản tương lai của khuôn khổ này đã giới thiệu một Combine phương pháp chung:

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

và giả sử C# được thay đổi như vậy + đã được dịch sang một cuộc gọi đến generic mới Combine<> phương pháp, sau đó contravariance và sự kết hợp đại biểu sẽ được cố định! Tôi đoán họ nói với chúng tôi rằng họ có những ưu tiên cao hơn, nhưng vẫn còn.

+1

Nên có bất kỳ vấn đề cơ bản với từng loại đại biểu xác định tĩnh 'Combine' phương pháp riêng của mình? Sau đó, nếu hai đại biểu 'X' và' Y' là cả hai loại được thay thế cho một 'FooDelegate', người ta có thể sử dụng' FooDelegate.Combine (X, Y) '. Ngay cả khi không có vấn đề hiệp phương sai, điều đó có vẻ sạch hơn '(FooDelegate) Delegate.Combine (X, Y)', và có thể thêm một kiểm tra biên dịch thời gian mà 'X' và' Y' là phù hợp. – supercat

+0

@supercat Với ​​tôi nghe như một giải pháp tốt. –

0

Bằng cách sử dụng "quá tải toán tử", bạn có thể thực hiện việc này trong các đối tượng của chính mình.

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; 

Kết quả: o3.Property = "Hello World!"

Vì vậy, tôi giả định framwork thực hiện somthing như thế này trong nền

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

Ồ vâng tôi biết về quá tải nhà điều hành Tôi không thể tìm thấy nó trong Reflactor và đã tự hỏi làm thế nào họ đã làm nó –

Các vấn đề liên quan