2011-08-16 45 views
8

Tôi đang gặp vấn đề thực sự lạ này với câu lệnh có điều kiện khi đặt giá trị Action<T>. Nó không phải là tôi không biết làm thế nào để làm việc xung quanh này vì nó khá dễ dàng để giải quyết bằng cách sử dụng một bình thường if.Tuyên bố điều kiện, đại biểu không cần thiết của đại biểu không cần thiết

Dưới đây là vấn đề của tôi:

public class Test 
{ 
    public bool Foo { get; set; } 
    public Action<bool> Action { get; set; } 

    public void A() 
    { 
     Action = Foo ? B : C;//Gives compiler error 
    } 

    public void B(bool value) 
    { 

    } 

    public void C(bool value) 
    { 

    } 
} 

này mang lại cho tôi một lỗi biên dịch với thông điệp

Không có chuyển đổi ngầm giữa 'phương pháp nhóm' và 'phương pháp nhóm'.

Điều kỳ lạ là tôi không thể hiểu tại sao điều này là bất hợp pháp.

Bằng cách này, cú pháp dưới đây sẽ làm cho điều này có hiệu lực (từ quan điểm trình biên dịch của view):

public void A() 
    { 
     Action = Foo ? (Action<bool>) B : C; 
    } 

Vì vậy, có lẽ bạn có thể đọc các câu hỏi như, tại sao các diễn viên cần thiết?

Trả lời

2

Bạn đang tạo hai khái niệm tương tự:

A) Nhóm phương pháp. Một nhóm phương thức là một hoặc nhiều phương thức C# có cùng tên. Nó là một trừu tượng được sử dụng chủ yếu bởi trình biên dịch; bạn không thể vượt qua xung quanh một nhóm phương pháp. Tất cả những gì bạn có thể làm với một nhóm phương thức là gọi nó hoặc tạo một delegate ra khỏi nó. Bạn hoàn toàn có thể tạo một đại biểu từ một nhóm phương thức nếu các loại chữ ký khớp với nhau.

B) Một đại biểu. Bạn biết những gì một đại biểu là; nó có một chữ ký kiểu cụ thể và đề cập trực tiếp đến một phương thức. Cũng như gọi nó, bạn có thể vượt qua nó và xử lý nó như là một đối tượng hạng nhất.

Vì vậy, trong ví dụ đầu tiên, biểu thức của bạn trả về một nhóm phương pháp B ở một bên và một nhóm phương pháp khác C ở phía bên kia. Toán tử bậc ba cần phải trả về cùng một kiểu trên cả hai mặt, nhưng nó không biết cái gì để đúc hai bên tới; loại biến mà bạn đã gán kết quả là (Action<bool>) không xác định loại biểu thức. Vì vậy, nó mơ hồ.

Trong ví dụ thứ hai, bạn hợp pháp đúc nhóm phương pháp B thành một đại diện Action<bool> ở một bên của toán tử bậc ba. Trong quá trình cố định hướng biểu thức, trình biên dịch cố gắng truyền mỗi bên sang loại phía bên kia. Nó có thể truyền thành công nhóm phương thức C đến một số Action<bool>, do đó nó thực hiện như vậy và biểu thức là hợp pháp.

-1

Hành động là một lớp đại biểu cụ thể và không có chuyển đổi tiềm ẩn nào có sẵn từ/cho một đại biểu thường xuyên có chữ ký tương tự.

+0

tôi nghĩ trình biên dịch C# đủ thông minh để kiểm tra xem ... –

1

BC không thực sự là đại biểu. Họ là các nhóm phương pháp, và họ có thể được chuyển đổi một cách ngụ ý cho các đại biểu (cụ thể là Action<bool>), nhưng đó không phải là điều tương tự.

Loại biểu thức có điều kiện phải nhất quán trên cả hai nhánh và vì BC hiện là nhóm phương pháp (không được nhập), trình biên dịch không thể tìm ra loại nên là gì. Như nó nói với bạn, không có chuyển đổi tiềm ẩn giữa chúng.

Đồng thời, nó không thể (hoặc ít nhất không) nhìn qua phía bên kia của toán tử gán và nói "oh, nó phải là Action<bool>".

Khi bạn thêm một dàn diễn viên, kiểu của biểu thức chi nhánh trái trở nên Action<bool>, và có một chuyển đổi ngầm giữa các nhóm phương pháp ở phía bên kia và đại biểu rằng, do trình biên dịch là hạnh phúc một lần nữa: các loại toàn bộ biểu thức là Action<bool>.

0

Tôi nghĩ rằng, Eric will again tell me, that my reasoning is slightly incorrect, nhưng tôi sẽ cho nó một thử anyway và hy vọng sửa chữa của mình :-)

Một nhóm phương pháp, ví dụ B, không có một loại, nó không phải là một đối tượng (B.GetType() sẽ không biên dịch).
Nó có thể dễ dàng được chuyển đổi thành một loại, đó là lý do tại sao một diễn viên tiềm ẩn tồn tại. mẫu:

Action<bool> a = B; // implicit cast taking place. 

Tuy nhiên, như bạn có thể thấy trong câu hỏi liên quan, khái niệm ternary cố gắng để tìm thấy một kiểu trả về là cả hai bộ phận của trận đấu biểu. Không biết rằng sau đó chuyển đổi thành Action<bool> sẽ xảy ra.Bởi vì các nhóm phương thức không có kiểu nào, nên không tồn tại sự chuyển đổi giữa chúng và B không thể chuyển đổi thành C và do đó, trình biên dịch chỉ phàn nàn về điều đó.

Bằng cách truyền bất kỳ phần nào của biểu thức bậc ba thành Action<bool>, bạn cho trình biên dịch biết rằng kiểu trả về phải là kiểu đó và nó kiểm tra xem phần khác của biểu thức bậc ba có hỗ trợ một phép diễn tiềm ẩn cho loại đó hay không. Vì đây là trường hợp, mã sẽ biên dịch.

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