2010-07-25 14 views
67

Tôi đang cố gắng viết một phương thức mở rộng trên các kiểu số để sử dụng trong một khuôn khổ kiểm tra thông thạo mà tôi đang xây dựng. Về cơ bản, tôi muốn làm điều này:Ràng buộc chung để đối sánh với các loại số

public static ShouldBeGreaterThan<T>(this T actual, T expected, string message) 
    where T : int || T: double || etc... 

Chỉ where T : struct không làm, vì đó cũng sẽ phù hợp stringbool, và có thể là cái gì khác tôi quên. có điều gì tôi có thể làm để chỉ khớp với các loại số không? (Các loại cụ thể triển khai các toán tử ><, vì vậy tôi có thể so sánh chúng ... Nếu điều này có nghĩa là tôi cũng đang đối sánh ngày, điều đó không quan trọng - tiện ích sẽ vẫn làm những gì tôi mong đợi.)

+6

Jon Skeet và Mark Gravell tập hợp một số lớp học thú vị cho điều này: http://www.yoda.arachsys.com/csharp/genericoperators.html –

+10

@ Thực sự nó là "Marc", nhưng tôi sẽ cho phép bạn tắt - Rất ít người hiểu đúng, p –

Trả lời

48

Trong trường hợp này bạn muốn hạn chế tới giao diện IComparable, cho phép bạn truy cập vào phương thức CompareTo, vì giao diện này cho phép bạn trả lời câu hỏi ShouldBeGreaterThan.

Các loại số sẽ triển khai giao diện đó và thực tế là nó cũng hoạt động trên các chuỗi không làm phiền bạn nhiều như vậy.

+1

Đây là giải pháp tốt hơn so với giao diện người dùng tổng quát hơn đối với các kiểu số, ít nhất là cho vấn đề này. –

+0

Có cách nào tôi có thể cho phép sử dụng '==' và '>' etc thay vì '.Equals()' và '.CompareTo'? –

5

Stackoverflow được rải rác với loại câu hỏi này. Take a look at this search. C# không hỗ trợ một cách để định nghĩa một kiểu generic bị ràng buộc bởi các số. Đáng buồn thay, đặt cược tốt nhất của bạn là triển khai phương pháp mở rộng trên tất cả các đối tượng và thực hiện chuyển đổi dựa trên loại hoặc để tạo một tập hợp các phương pháp cho ints, double, float, v.v.

15
public static bool IsGreaterThan<T>(this T actual, T comp) where T : IComparable<T> 
{ 
    return actual.CompareTo(comp) > 0; 
} 

Bạn có thể thêm ràng buộc cấu trúc nếu bạn muốn.

6

Rất khó để giới hạn chỉ số, vì không có gì phổ biến như INumeric để sử dụng làm bộ lọc. Trên thực tế, tôi nghi ngờ cách tiếp cận dễ nhất ở đây là không phải nhấn mạnh vào ràng buộc và sử dụng Comparer<T>.Default.Compare bên trong phương thức.

Loại inbuilt này hỗ trợ cả kiểu chung chung IComparable<T> và không chung chung IComparable và hỗ trợ kiểu ref, loại giá trị và nâng mức sử dụng qua Nullable<T>.

Đối với đầy đủ hành sử dụng, nhìn vào MiscUtil's Operator classGreaterThan vv, mà có thể hữu ích nếu bạn thực sự muốn sử dụng các nhà điều hành (chứ không phải giao diện). Nó cũng cung cấp quyền truy cập cho các nhà khai thác khác như Add v.v.

+0

Marc Gravell nói "Thật khó ** để giới hạn chỉ số" nhưng có thể ** cả trong thời gian chạy và thời gian biên dịch. Vui lòng xem câu trả lời của tôi cho "Có ràng buộc nào hạn chế phương pháp chung của tôi đối với các loại số không?" câu hỏi.https: //stackoverflow.com/questions/32664/is-there-a-constraint-that-restricts-my-generic-method-to-numeric-types –

+1

@Erez sẽ hoạt động nhưng sẽ chết hiệu suất mã quan trọng - rất nhiều boxing và loại kiểm tra. Một nơi nào đó trong thời gian C# 7.2-C# 8.0, chúng tôi có thể thấy bổ sung cho generics để làm điều này hiệu quả hơn nhiều. –

+0

Tôi không thể đợi cho đến khi điều này được Microsoft hỗ trợ. –

38
where T : struct, 
      IComparable, 
      IComparable<T>, 
      IConvertible, 
      IEquatable<T>, 
      IFormattable 

Đó là gần nhất tôi có thể bị ràng buộc bằng số. Tất cả các kiểu số thực hiện 5 giao diện này, nhưng IFormattable không được thực hiện bởi bool, và các chuỗi là một kiểu tham chiếu, vì vậy chúng không thể áp dụng được.

Có một số thứ khác thực hiện những điều này - ví dụ DateTime, vì vậy nó không thực sự được yêu cầu, nhưng ngăn chặn rất nhiều cảnh báo bạn không muốn.

+0

Ngay cả với điều này, tôi dường như không thể sử dụng các phép toán phổ biến. Không thể áp dụng toán tử 'Operator '==' cho các toán hạng kiểu 'T' và 'float'' –