2013-05-02 30 views
11

Tôi đã tìm thấy hai cách khác nhau để khởi tạo một Đại biểu với một Hành động:Hành động để ủy quyền: Hành động mới hoặc truyền Hành động?

Tạo một hành động mới hoặc truyền tới Hành động.

Delegate foo = new Action(() => DoNothing(param)); 
Delegate bar = (Action)(() => DoNothing(param)); 

Có sự khác biệt giữa 2 cú pháp này không?

Cái nào tốt hơn và tại sao?

Edit:
đại biểu là sử dụng trong ví dụ này vì cú pháp rất hữu ích để gọi các phương thức như BeginInvoke hoặc Gọi với một biểu thức lambda, và điều quan trọng là để cast biểu thức lambda vào một hành động

static main 
{ 
    Invoke((Action)(() => DoNothing())); // OK 
    Invoke(new Action(() => DoNothing())); // OK 
    Invoke(() => DoNothing()); // Doesn't compil 
} 

private static void Invoke(Delegate del) { } 

Nhưng thật thú vị khi thấy trình biên dịch được ủy quyền này:

Action action =() => DoNothing(); 
Invoke(action); 
+0

Để chỉnh sửa của bạn: Điều gì có ý nghĩa nội dung sẽ có trong phương thức 'static'' Invoke' của bạn? –

+0

Không có gì thú vị. Mục đích của câu hỏi là chỉ để hiểu sự khác biệt giữa 2 cú pháp. Thực hiện thực sự của tôi là trong một ứng dụng WPF khi tôi gọi Dispatcher.Invoke() (http://msdn.microsoft.com/en-us/library/cc647509(v=vs.100).aspx) – Hyralex

+1

Tôi thấy. Bạn vẫn nên nhớ rằng 'Action' ___is___ a' Delegate', vì 'Action' xuất phát từ' Delegate'. Vì vậy, ngay cả khi bạn sử dụng một quá tải mà mất trong một 'đại biểu', bạn có thể cho nó một' hành động'. Ví dụ: 'Action bar =() => DoNothing (param); someDispatcher.BeginInvoke (bar); '(xem [' Dispatcher.BeginInvoke'] (http://msdn.microsoft.com/en-us/library/cc190824.aspx)). Ngoài ra: Trong một phiên bản mới hơn của khung công tác .NET 4.5, có quá tải 'Dispatcher.Invoke' lấy' Action', nhưng đó chỉ là để thuận tiện, xem http://msdn.microsoft.com/en-us/library /hh199416.aspx. –

Trả lời

10

Không có sự khác biệt giữa hai hướng dẫn này. Trong cả hai hướng dẫn, một thể hiện hành động mới được tạo ra.

Mã IL bên dưới dường như xác nhận điều này.

điều khiển chương trình:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Delegate barInit = (Action)(() => DoNothing()); 
     Delegate fooInit = new Action(() => DoNothing()); 
    } 

    private static void DoNothing() { } 
} 

IL Code:

// First instruction 
IL_0000: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate2' 
IL_0005: brtrue.s IL_0018 

IL_0007: ldnull 
IL_0008: ldftn void CodeMachineTest.Program::'<Main>b__0'() 

// Create a new Action instance for the instruction (Action)(() => DoNothing()) 
IL_000e: newobj instance void [mscorlib]System.Action::.ctor(object, native int) 

IL_0013: stsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate2' 

IL_0018: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate2' 
IL_001d: pop 

// Second instruction 
IL_001e: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate3' 
IL_0023: brtrue.s IL_0036 

IL_0025: ldnull 
IL_0026: ldftn void CodeMachineTest.Program::'<Main>b__1'() 
IL_002c: newobj instance void [mscorlib]System.Action::.ctor(object, native int) 
IL_0031: stsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate3' 

IL_0036: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate3' 
IL_003b: pop 
IL_003c: ret 
2

Tôi không có sự khác biệt.

new Action(() => DoNothing(param)); 

Điều này chỉ tạo một Hành động mới và chuyển qua biểu thức Lambda, trình biên dịch sẽ xử lý và thấy rằng mọi thứ đều được kết nối tốt.

(Action)(() => DoNothing(param)); 

này hoạt động vì một phương pháp lambda như thế này trả về không có giá trị và mất không tham số, như vậy trình biên dịch có thể xác minh rằng nó là "trí trên bản đồ" đến một hành động với lý do nó đi qua hệ thống đại biểu.

Chúng nhiều hoặc ít và giống nhau, tùy thuộc vào bất kỳ loại tối ưu hóa trình biên dịch nào khó có thể nói hiệu quả hơn, có lẽ bạn nên kiểm tra hiệu suất và tự mình xem?

Đó là một câu hỏi thú vị và thăm dò vào hệ thống Đoàn và làm thế nào LINQ và những biểu hiện phù hợp

new Func<string>(() => "Boo!"); 

là nhiều hay ít tương đương với:.

(Func<String>)() => "Boo!"; 

Theo như tôi nhận thức được rằng cả hai đều sẽ đi xuống thông qua hệ thống đại biểu nghĩ rằng Invoke() vv, nó sẽ là thú vị nếu bạn đã kiểm tra hiệu suất và chia sẻ kết quả của bạn.

+1

Tôi đã làm một số thử nghiệm và không có sự khác biệt. Sau khi tháo gỡ, mã IL và mã máy giống nhau. – Hyralex

+1

Nó không đặc biệt thú vị, chúng chỉ là hai cú pháp dẫn đến cùng một IL. Vì vậy, điều này không có liên quan đến hiệu suất, vì vậy những gì bạn muốn anh ta chia sẻ? Đọc Đặc tả Ngôn ngữ C# nếu bạn muốn biết chi tiết. Biểu thức đầu tiên nằm trong _7.6.10.5 Biểu thức tạo đại biểu ủy nhiệm_ và biểu thức thứ hai là _6.5 Chuyển đổi hàm ẩn danh_. Số phần là từ phiên bản 5.0 của tài liệu. Lưu ý rằng 7.6.10.5 rõ ràng nói rằng nó được xử lý giống như trong 6.5. –

0

Không có sự khác biệt, chúng tôi chỉ hai cú pháp cho cùng. Cá nhân, tôi sử dụng cái cuối cùng, vì nó ngắn hơn.

Nhưng tại sao bạn cần biến loại Delegate? Trong hầu hết các trường hợp, bạn muốn biến để có các loại tương tự như ví dụ, và sau đó bạn có thể sử dụng

var bar = (Action)(() => DoNothing(param)); 

hoặc

Action bar =() => DoNothing(param); 

thay vì

Delegate bar = (Action)(() => DoNothing(param)); // (from your question) 
+0

Một số phương thức như Invoke hoặc BeginInvoke cần một Delegate, và nó cần thiết để tạo hoặc tạo một Action để sử dụng biểu thức lambda. – Hyralex

+0

@Hyralex Nhưng tất cả các loại ủy nhiệm cụ thể, bao gồm 'System.Action', lấy được (thông qua' System.MulticastDelegate') từ 'System.Delegate'. Do đó, các phương thức 'Invoke' và' BeginInvoke' và các thành viên khác được kế thừa. Vì vậy, bạn có thể nói ví dụ: 'Action bar =() => DoNothing (param); bar.BeginInvoke (...); '. Vì vậy, tôi không hiểu. –

+0

Tôi đang nói về BeginInvoke và Invoke của đối tượng hiện có như Dispatcher. Tôi đã chỉnh sửa câu hỏi của mình để đưa thêm ví dụ. – Hyralex

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