2012-07-03 35 views
18

Tôi đang cố gắng sử dụng toán tử điều kiện (ternary) để gán biểu thức lambda thích hợp cho biến, tùy thuộc vào điều kiện, nhưng tôi gặp lỗi trình biên dịch: Loại biểu thức điều kiện không thể được xác định bởi vì không có chuyển đổi tiềm ẩn giữa 'biểu thức lambda' và 'biểu thức lambda'. Tôi có thể sử dụng if-else bình thường để giải quyết vấn đề này, nhưng toán tử có điều kiện có ý nghĩa hơn với tôi (trong ngữ cảnh này), sẽ làm cho mã ngắn gọn hơn, ít nhất, tôi muốn biết lý do tại sao nó không ' t làm việc.Chỉ định biểu thức lambda sử dụng toán tử điều kiện (ternary)

// this code compiles, but is ugly! :) 
Action<int> hh; 
if (1 == 2) hh = (int n) => Console.WriteLine("nope {0}", n); 
else hh = (int n) => Console.WriteLine("nun {0}", n); 

// this does not compile 
Action<int> ff = (1 == 2) 
    ? (int n) => Console.WriteLine("nope {0}", n) 
    : (int n) => Console.WriteLine("nun {0}", n); 
+0

Cảm ơn sự giàu có của bạn.okelly, Nikhil Agrawal, Romain Verdier và Alex! Tất cả các câu trả lời của bạn là chính xác (biên dịch và đưa ra kết quả chính xác), nhưng sự lựa chọn của tôi đi đến rich.okelly vì lời giải thích của ông. –

Trả lời

18

Các biên dịch C# sẽ cố gắng để tạo ra một cách độc lập lambdas và không thể rõ ràng xác định loại.Đúc có thể thông báo cho trình biên dịch loại sử dụng:

Action<int> ff = (1 == 2) 
    ? (Action<int>)((int n) => Console.WriteLine("nope {0}", n)) 
    : (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 
15

Điều này sẽ hiệu quả.

Action<int> ff = (1 == 2) 
? (Action<int>)((int n) => Console.WriteLine("nope {0}", n)) 
: (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 

Có hai vấn đề ở đây

  1. Biểu
  2. ternary hành

1. Vấn đề với Expression

Trình biên dịch được nói cho bạn biết chính xác những gì sai - 'Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'.

Điều đó có nghĩa là những gì bạn đã viết là biểu thức lambda và biến kết quả cũng là biểu thức lambda.

Biểu thức lambda không có bất kỳ loại cụ thể nào - nó chỉ có thể chuyển đổi thành cây biểu thức.

Một biểu thành viên truy cập (mà là những gì bạn đang cố gắng để làm) chỉ có sẵn trong các hình thức

primary-expression . identifier type-argument-list(opt) 
predefined-type . identifier type-argument-list(opt) 
qualified-alias-member . identifier type-argument-list(opt) 

... và một biểu thức lambda không phải là một biểu thức chính.

2. Vấn đề với ternary hành

Nếu chúng ta làm

bool? br = (1 == 2) ? true: null; 

Điều này dẫn đến lỗi nói chính xác như của bạn. 'Type of conditional expression cannot be determined because there is no implicit conversion between 'bool' and '<null>'

Nhưng lỗi đã biến mất nếu chúng ta làm

bool? br = (1 == 2) ? (bool?)true: (bool?)null; 

Đúc này một mặt cũng sẽ làm việc

bool? br = (1 == 2) ? (bool?)true: null; 

HOẶC

bool? br = (1 == 2) ? true: (bool?)null; 

Đối với trường hợp của bạn

Action<int> ff = (1 == 2) 
? (Action<int>)((int n) => Console.WriteLine("nope {0}", n)) 
: ((int n) => Console.WriteLine("nun {0}", n)); 

HOẶC

Action<int> ff = (1 == 2) 
? ((int n) => Console.WriteLine("nope {0}", n)) 
: (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 
+0

+1 nhanh chóng và hoàn hảo – Habib

+0

câu trả lời tuyệt vời, thẳng đến mức có ví dụ rõ ràng ... cảm ơn bạn – Dal

+0

@Dal: Cảm ơn. :) –

3

Về cơ bản các câu trả lời tương tự như những người khác, trong một hình thức khác nhau

Action<int> ff = (1 == 2) 
? new Action<int>(n => Console.WriteLine("nope {0}", n)) 
: new Action<int>(n => Console.WriteLine("nun {0}", n)); 
4

Trong thực tế, với kiểu suy luận, bạn có thể:

  • Sử dụng var cho biến cục bộ
  • Chỉ truyền biểu thức đầu tiên của toán tử bậc ba
  • Bỏ loại tham số lambda vì nó có thể được suy ra

Kết quả là ngắn gọn hơn nhiều. (Tôi cho phép bạn quyết định xem nó có dễ đọc hơn không.)

var ff = condition 
      ? (Action<int>)(n => Console.WriteLine("nope {0}", n)) 
      : n => Console.WriteLine("nun {0}", n); 
Các vấn đề liên quan