5

Cho hai triển khai các phương pháp so sánh:nhà điều hành có điều kiện và so sánh Đại biểu

// compares by Key... 
private static int CompareByKey(KeyValuePair<int, string> x, KeyValuePair<int, string> y) 

{ 
    return x.Key.CompareTo(y.Key); 
} 

// compares by Value... 
private static int CompareByValue(KeyValuePair<int, string> x, KeyValuePair<int, string> y) 
{ 
    return x.Value.CompareTo(y.Value); 
} 

Tại sao không phải là điều kiện điều hành khối mã biên dịch sau:

Comparison<KeyValuePair<int, string>> sortMethod; 
sortMethod = isSortByActualValue ? CompareByKey : CompareByValue; 

biên dịch báo lỗi: "Loại biểu thức điều kiện không thể được xác định vì không có chuyển đổi tiềm ẩn giữa 'nhóm phương pháp' và 'nhóm phương pháp' "

Tuy nhiên, khối mã tương đương sử dụng if-else d oes không có bất kỳ vấn đề:

Comparison<KeyValuePair<int, string>> sortMethod; 
if (isSortByActualValue) 
    sortMethod = CompareByKey; 
else 
    sortMethod = CompareByValue; 

(tất cả đều tốt trong cả hai bài tập trên)

Vì vậy, hiện các nhà điều hành có điều kiện, nếu tôi đúc các đại biểu So sánh:

Comparison<KeyValuePair<int, string>> sortMethod; 
sortMethod = isSortByActualValue ? (Comparison<KeyValuePair<int, string>>) CompareByKey : CompareByValue; 

(tất cả tốt trong phân công ở trên, khi truyền ngay cả khi truyền chỉ ở phần thực)

+2

CompareByAcutalValue và CompareByDisplayValue được xác định như thế nào? Bạn chỉ hiển thị định nghĩa cho CompareByKey và CompareByValue. –

+0

Đoạn mã trong bài đăng của tôi đã được chỉnh sửa để rõ ràng. Tôi đã không nhận ra rằng tôi đã thay đổi tên (của phương pháp) chỉ một phần. Cảm ơn Eric, tôi đã cập nhật tất cả các tham chiếu đến CompareByActualValue để CompareByKey (và CompareByDisplayValue thành CompareByValue). – Arun

Trả lời

7

Phương pháp lỗi thực sự nói tất cả nhưng nó không hoàn toàn trực quan. Nếu bạn sử dụng tên phương thức mà không cần gọi phương thức, bạn đang xử lý một nhóm phương pháp . "Nhóm", bởi vì một phương pháp có thể bị quá tải và tên có thể chỉ ra bất kỳ phương thức quá tải nào.

Bây giờ, các nhóm phương pháp có thể chuyển đổi hoàn toàn thành đại biểu có chữ ký phù hợp, đây là lý do tại sao nhiệm vụ của bạn trong if hoạt động.

Cho đến nay, rất tốt. Tuy nhiên, toán tử điều kiện ?: cần suy ra một loại phổ biến mà đối số thứ hai và thứ ba của nó có thể được chuyển đổi hoàn toàn, và nó không xem xét tất cả các chuyển đổi cho điều đó (điều này sẽ có vấn đề đa dạng). Nó chỉ đơn thuần là liệu cả hai đối số có cùng một loại hay không hoặc liệu một đối số có chuyển đổi hoàn toàn vào loại kia hay không. Đây không phải là trường hợp ở đây: mặc dù cả hai đối số đều là nhóm phương pháp, nhưng thực ra chúng là nhóm phương pháp khác nhau với các loại riêng biệt và bạn không thể chuyển đổi nhóm phương thức này thành nhóm phương pháp khác. Mặc dù cả hai có thể dễ dàng được chuyển đổi thành một đại biểu, trình biên dịch cấm việc sử dụng này.

Điều này cũng đúng đối với các loại khác, bằng cách này:

object = someBool ? "" : New List<Integer>(); 

cũng thất bại trong việc biên dịch, vì lý do tương tự. Và một lần nữa, chúng ta có thể làm cho điều này biên dịch bằng cách đúc một cách rõ ràng một trong các đối số cho một loại cơ sở chung:

object = someBool ? (object) "" : New List<Integer>(); 
+1

+1, nhưng tôi muốn thay đổi "cần phải suy ra loại đối số thứ hai và thứ ba" thành "cần suy ra loại phổ biến mà đối số thứ hai và thứ ba của nó có thể được chuyển đổi hoàn toàn" – phoog

+0

Vậy tại sao không 'isSortByActualValue ? CompareByKey: So sánh biên dịch của Soạn thảo? Họ không phải là nhóm phương pháp giống nhau sao? – svick

+0

@svick Không tồn tại chuyển đổi từ nhóm phương pháp thành nhóm phương pháp, bất kể nhóm phương pháp. Tôi nên đã làm cho rõ ràng hơn, và đó là một trường hợp khá cụ thể vì không có loại bình thường thiếu sự chuyển đổi này. Tôi không biết làm thế nào điều này là chính xác nêu trong C# đặc điểm kỹ thuật. –

3

Nếu bạn có một biểu hiện như CompareByKey của bạn, nó không có bất kỳ loại Net cụ thể, nhưng có một loại "nhóm phương pháp" đặc biệt. Đó là bởi vì bạn có thể có một số phương pháp được gọi là CompareByKey và không rõ bạn muốn cái nào (và nó hoạt động giống hệt nhau ngay cả khi bạn chỉ có một phương pháp). Ngoài ra, bạn không rõ loại đại biểu nào bạn muốn, ví dụ: Comparison<KeyValuePair<int, string>> hoặc Func<KeyValuePair<int, string>, int>.

Bạn có thể làm gì với các nhóm phương pháp? Bạn có thể sử dụng chúng để tạo một đại biểu một cách rõ ràng (new Comparison<KeyValuePair<int, string>>(CompareByKey)) và chúng cũng được chuyển đổi hoàn toàn cho các đại biểu. Đây là lý do tại sao phiên bản if của bạn hoạt động.

Vì vậy, điều đó có liên quan gì đến vấn đề của bạn? Khi bạn có một toán tử có điều kiện, trình biên dịch phải tìm ra kiểu của toàn bộ biểu thức và nó không thể sử dụng kiểu biến mà bạn gán cho nó (đó không phải là cách suy luận kiểu hoạt động trong C#). Và vì cả hai biểu thức là các nhóm phương thức và các nhóm phương thức được coi là các kiểu khác nhau không có chuyển đổi tiềm ẩn giữa nhau, nên không thể xác định được toàn bộ biểu thức. Đó là lý do tại sao bạn nhận được lỗi.

Bạn đã tìm thấy bản sửa lỗi: hoặc không sử dụng toán tử có điều kiện hoặc chỉ định loại của một toán hạng một cách rõ ràng bằng cách sử dụng một hàm tạo (hoặc hàm tạo đại biểu).

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