2011-11-18 16 views
12

Tôi đã viết một Generic Class :Làm cách nào tôi có thể trừ hai đối tượng chung (T - T) trong C# (Ví dụ: DateTime - DateTime)?

public class Interval<T> where T : IComparable // for checking that Start < End 
{ 
    public T Start { get; set; } 
    public T End { get; set; } 
    ... 
} 

Và tôi sử dụng lớp này với DateTime, int, vv

Tôi cần một Thời gian tài sản mà trả một khoảng thời gian như:

public object Duration 
{ 
    get 
    { 
     return End - Start; 
    } 
} 

Nhưng khi thuộc tính này được bao gồm trong lớp của tôi, trình biên dịch sẽ tăng ra một lỗi logic trên toán tử -.

Tôi có thể làm gì để đạt được mục tiêu này bình thường, hoặc tôi có nên bỏ qua không?

+1

Và trình biên dịch biết rằng loại bạn đang sử dụng có toán tử '-' được định nghĩa như thế nào? – Oded

+0

Điều này có thể giúp: http://stackoverflow.com/questions/171664/how-to-turn-these-3-methods-into-one-using-c-sharp-generics, kiểm tra Marc Gravells đăng trên arithmetics chung. – Alex

+0

Có thể trùng lặp: http://stackoverflow.com/questions/5516459/constrain-type-to-allow-addition-subtraction-operations-in-c-sharp – Reddog

Trả lời

3

Hãy thử một cái gì đó như điều này:

static void Main(string[] args) 
{ 
    Tuple<int, bool> value = JustAMethod<int>(5, 3); 
    if (value.Item2) 
    { 
     Console.WriteLine(value.Item1); 
    } 
    else 
    { 
     Console.WriteLine("Can't substract."); 
    } 
} 
public static Tuple<T, bool> JustAMethod<T>(T arg1, T arg2) 
{ 
    dynamic dArg1 = (dynamic)arg1; 
    dynamic dArg2 = (dynamic)arg2; 
    dynamic ret; 
    try 
    { 
     ret = dArg1 - dArg2; 
     return new Tuple<T, bool>(ret, true); 
    } 
    catch 
    { 
     return new Tuple<T, bool>(default(T), false); 
    } 
} 

Cách thức hoạt động: trước tiên, bạn chuyển đổi đối số thành loại động và bạn có thể dễ dàng sử dụng toán tử trên loại động. Nếu bạn không thể sử dụng các toán tử, thì một ngoại lệ sẽ được ném vào thời gian chạy.Vì vậy, nếu bạn cố gắng trừ hai đối tượng mà bạn thực sự không thể trừ, chúng tôi sẽ bắt ngoại lệ và trả về false làm mục thứ hai trong số Tuple.

1

Trình biên dịch thực hiện việc này để bạn không viết mã lỗi, toàn bộ điểm chung của nó và khái niệm về lập trình kiểu an toàn.

Nếu bạn cần một phương pháp trừ ngày ghi một ngày chấp nhận một ngày, và nếu bạn cần một số khác cho số nguyên, hãy đoán bạn nên viết một số cho số nguyên. Generics không có để trình biên dịch có thể chịu trách nhiệm cho bất kỳ loại nào. Hãy suy nghĩ về nó nếu tôi muốn sự khác biệt giữa hai đối tượng, làm thế nào tôi sẽ làm điều đó với phương pháp chung của bạn?

Hoặc như @Reed Copsey đã đề cập, bạn có thể hạn chế một lớp học với nó.

+0

Có, nhưng đây không phải là câu hỏi của tôi, tôi nói tại sao không? –

+0

Và tôi đã cho bạn một câu trả lời 'bạn viết một phương pháp cho int và bạn viết một cho ngày', generics cung cấp loại an toàn, nó không phải là lý do tại sao nó là gì. – JonH

+0

Tôi đứng lên cho những gì tôi đã nói, sẵn sàng để có downvote @RedHat. – JonH

7

Điều này là không thể với generics trong C# - ít nhất là không trực tiếp. Nó đã là một highly requested feature on Connect trong một thời gian dài. Bạn sẽ cần phải làm cho các loại của bạn triển khai một số giao diện có thành viên có thể được sử dụng và hạn chế lớp đó hoặc sử dụng một trong các giải pháp được liệt kê trong lỗi Kết nối (không có cách nào là hoàn hảo) hoặc một cách tiếp cận riêng biệt như MiscUtil's generic operators.

+1

+1 cho cách tiếp cận giao diện. – MPelletier

1

Mặc dù điều này có vẻ giống như một hạn chế lớn, bạn cần nhớ rằng generics là chung. Tất nhiên, loại System.Int32 có thể hoạt động tốt với các toán tử nhị phân của C#. Tuy nhiên, vì lợi ích của đối số, nếu <T> là loại lớp hoặc cấu trúc tùy chỉnh, trình biên dịch không thể giả định nó đã quá tải các toán tử +, -, */.

4

công việc này

public object Duration 
{ 
    get 
    { 
     return (dynamic)End - (dynamic)Start; 
    } 
} 

nhưng không kiểm tra, và chậm

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