2009-09-03 42 views
6

Tôi muốn viết phương thức C# có thể chấp nhận bất kỳ số nào. Một cái gì đó như:C# số lớp cơ sở

Nhưng tôi không thấy lớp cơ sở "số" trong C#, như tồn tại trong hầu hết các ngôn ngữ khác mà tôi đã sử dụng. Các kiểu giá trị số là IComparable, IFormattable, IConvertible, IComparable và IEquatable, nhưng không có gì có vẻ như có bất kỳ khả năng số học nào. Họ là tất cả các cấu trúc, không có siêu lớp phổ biến rõ ràng, ngoài đối tượng. (Tha thứ cho tôi nếu tôi đang hiểu rõ ý nghĩa ở đây, vì tôi không quá quen thuộc với các cấu trúc C# và chính xác tất cả các cách mà chúng giống hoặc không giống như các lớp.)

Tôi thiếu thứ gì đó hoặc không thể thế nào để viết một phương thức trong C# có "a + b" mà không khai báo chính xác những gì a và b nằm trong ngữ cảnh của "+"?

+0

(Đã trả lời nhận xét; để làm rõ - ở đó ** không có quá trình truyền hoặc quá tải) –

+0

(Hãy bình luận khác về 'IEnumerable.Sum'; lưu ý rằng MiscUtil cung cấp các phiên bản chung của' Sum', 'Average' , vv - sử dụng 'Toán tử 'vv) –

Trả lời

3

Bạn sẽ phải sử dụng quá tải. Một chút giống như lớp Math đang hoạt động với chức năng như Math.Max, nơi nó hỗ trợ tất cả các loại số.

link được CD đề xuất cũng có hiệu quả.

+0

Hoặc giống như các phương thức mở rộng LINQ đang làm với IEnumerable.Sum và chỉ thực hiện một nửa số kiểu số! – Ken

+0

Không nhất thiết. Có các giải pháp dựa trên chung chung (xem câu trả lời của tôi để biết thêm). –

2

Thật không may, không có lớp/giao diện như vậy tồn tại.

0

Điều tốt nhất bạn có thể làm là where T : struct yêu cầu ValueType; tất cả các số đều là ValueTypes.

Thật không may, vì vậy tất cả các cấu trúc do người dùng xác định, do đó, đó là nhược điểm. Không có chung chung cụ thể mà sẽ chấp nhận tất cả các lớp số.

Tôi ngần ngại thậm chí đề nghị này, nhưng bạn có thể xem xét kiểm tra thời gian chạy chống lại các loại T trong phương pháp và ném nếu T không phải là một int, long, short, float, hoặc gấp đôi. Thật không may, điều này sẽ không giúp một lập trình viên tại thời gian biên dịch.

2

int và các loại số khác là ValueTypes. Như đã nói, tất cả những gì bạn có thể làm là nói where T: struct. Vâng, bạn có thể sử dụng sự phản chiếu để kiểm tra xem đối số kiểu có thực hiện thêm hay không ... nhưng tôi không chắc đó có phải là một ý hay hay không.

3

Xem this SO question để thảo luận tương tự.

Ngoài ra, bạn có thể làm điều này (với một số nỗ lực tẻ nhạt) nếu bạn sẵn sàng để tạo ra các loại riêng biệt cho mỗi loại số lõi Net bạn muốn sử dụng nó cho ...

Tạo hai cấu trúc , được gọi là say, MyInt và MyDecimal hoạt động như mặt tiền đối với các loại lõi CTS Int32 và Thập phân (Chúng chứa một trường nội bộ của loại tương ứng đó.) Mỗi ​​loại phải có một ctor lấy một thể hiện của kiểu CTS lõi làm tham số đầu vào ..

Làm cho mỗi người triển khai giao diện trống gọi là INumeric

Sau đó, theo phương pháp chung của bạn, mak e ràng buộc dựa trên giao diện này. Nhược điểm, ở khắp mọi nơi bạn muốn sử dụng các phương pháp này, bạn phải xây dựng một thể hiện của các loại tùy chỉnh thích hợp thay vì loại CTS lõi, và vượt qua các loại tùy chỉnh cho phương pháp.

LƯU Ý: mã hóa các cấu trúc tùy chỉnh để mô phỏng tất cả hành vi của các loại CTS lõi là phần tẻ nhạt ... Bạn phải triển khai một số giao diện CLR tích hợp (IComparable, v.v.) và quá tải tất cả số học, và toán tử boolean ...

0

Đây là câu hỏi rất phổ biến; nếu bạn đang sử dụng .NET 3.5, có rất nhiều sự hỗ trợ cho điều này trong MiscUtil, thông qua lớp Operator, hỗ trợ các loại sẵn có và bất kỳ kiểu tùy chỉnh nào với các toán tử (bao gồm các toán tử "dỡ bỏ"); Đặc biệt, điều này cho phép sử dụng với Generics, ví dụ:

public static T Sum<T>(this IEnumerable<T> source) { 
    T sum = Operator<T>.Zero; 
    foreach (T value in source) { 
     if (value != null) { 
      sum = Operator.Add(sum, value); 
     } 
    } 
    return sum; 
} 

Hoặc ví dụ khác; Complex<T>

+0

Đó là loại gọn gàng (hoặc tổng) mà có một thư viện để làm tất cả các quá tải và đúc cho tôi, nhưng tôi không xem xét "Operator.Add (a, b)" là một giải pháp cho vấn đề của "a + b "không phải là chung chung. Nếu tôi muốn trở thành chung chung bằng cách viết một loạt các mã tiết, tôi không cần thư viện của bên thứ ba để làm điều đó. :-) – Ken

+0

Có * là * không bị quá tải hoặc truyền. Đó là mã dựa trên chung chung chính hãng, với một số sử dụng thông minh của Expression để biên dịch trước một đại biểu (mỗi loại) có thể làm số học. –

+0

Nó có thể giúp đỡ nếu tôi làm rõ rằng 'Thêm' thực sự là một phương pháp chung (' Thêm '); đơn giản là trong ví dụ chúng ta đang sử dụng kiểu-type-inference để tránh phải thêm ''. Nhưng nó vẫn còn đó. –

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