2010-06-15 6 views
15

Dường như C# không hỗ trợ C++ như mẫu. Ví dụ:Chức năng mẫu trong C# - Loại trả về?

template <class myType> 
myType GetMax (myType a, myType b) { 
return (a>b?a:b); 
} 

Tôi muốn hàm của tôi có kiểu trả về dựa trên các tham số của nó, làm thế nào tôi có thể đạt được điều này trong C#? Cách sử dụng mẫu trong C#

EDIT: Tôi có thể sử dụng đối tượng và getType cho mục đích tương tự không?

+0

tôi không thấy làm thế nào bạn muốn sử dụng GetType để thực hiện điều tương tự, không có. Và bạn không muốn một đối tượng trả về API, trừ khi bạn hài lòng với người gọi phải truyền khắp nơi. –

Trả lời

31

Gần nhất với C mẫu ++ trong C# là Generics - nhưng họ không phải là rất gần. Cụ thể, bạn không thể sử dụng toán tử như > giữa các giá trị loại chung, bởi vì trình biên dịch không biết về chúng (và bạn không thể hạn chế các loại dựa trên toán tử). Mặt khác, bạn có thể viết:

public T GetMax<T>(T lhs, T rhs) 
{ 
    return Comparer<T>.Default.Compare(lhs, rhs) > 0 ? lhs : rhs; 
} 

hoặc

public T GetMax<T>(T lhs, T rhs) where T : IComparable<T> 
{ 
    return lhs.CompareTo(rhs) > 0 ? lhs : rhs; 
} 

Lưu ý rằng người đầu tiên trong số này là null-an toàn; thứ hai là không.

Mô tả đầy đủ về generics cũng nằm ngoài phạm vi của câu trả lời Stack Overflow; MSDN có một số thông tin hoặc tham khảo sách C# yêu thích của bạn.

+1

Tôi đã nghe C# ở độ sâu có một số giải thích tốt về generics :) – SWeko

+1

Hàm i đưa ra chỉ là một mẫu, Còn về các hàm khác ngoài so sánh thì sao? – SMUsamaShah

+0

@ Life2HO: Vâng, bạn muốn hàm nào? Nó là một phương pháp thể hiện được chỉ định trong một giao diện? Nếu vậy, bạn ổn. –

0

Generics!

class MyClass<T> where T : IEnumerable (any parent class here!) 
{ 
    T myGeneric {get; set;} 
} 
1

Bạn sẽ muốn xem generics. Cú pháp:

public T GetMax<T>(T a, T b) { 
    return (a>b?a:b); 
} 

CẬP NHẬT vì một số ý kiến ​​... Tôi chỉ muốn cung cấp một cái nhìn tổng quan rất nhanh chóng. Vâng tôi đoán nó không biên dịch hoặc thực thi đúng cách. Nhưng đây là ý tưởng cơ bản về cách thức này sẽ như thế nào. Bạn sẽ tìm thấy câu trả lời đầy đủ hơn về chủ đề này - trong khi đó.

Execution Cú pháp:

int a = 5; 
int b = 10; 
int result = GetMax(a, b); 

Hope this helps,

Kính trọng, Thomas

+0

Tôi sắp sửa nói như vậy nhưng điều đó sẽ không biên dịch vì trả về dòng (a> b? A: b); ' Anh ta sẽ cần một ràng buộc giao diện hoặc một cái gì đó ... –

+1

Bạn không thể so sánh a và b theo cách này, vì trình biên dịch không biết T là gì. Nếu loại T không hỗ trợ so sánh thì sao? –

2

Mã của bạn sẽ trở thành một cái gì đó như thế này:

public T GetMax<T>(T a, T b) where T : IComparable<T> 
{ 
    return a.CompareTo(b) > 0 ? a : b; 
} 
6

Generics trong C# là không mạnh như các mẫu trong C++. Những gì bạn muốn làm không hoạt động trong C#.

Một hack/workaround cho tình hình của bạn là

public T GetMax<T>(T a, T b) where T: IComparable { 
    if(a.CompareTo(b) > 0) { 
     return a; 
    } 
    return b; 
} 
+0

Hàm i đưa ra chỉ là một mẫu, Còn về các hàm khác ngoài so sánh thì sao? – SMUsamaShah

+1

@ LifeH2O: Nó phụ thuộc - là nó được chỉ định trong một giao diện? Nếu vậy, bạn có thể hạn chế kiểu generic để thực hiện giao diện (hoặc lấy được từ một lớp cơ sở nhất định, vv). –

+1

Là một nhà phát triển C++, bạn có thể thấy mình thất vọng với các generics của C#. Nhưng chúng vẫn hữu ích trong nhiều tình huống và đáng học hỏi. –

0

Bạn có nghĩa là một số điều như thế này

public static IEnumerable<TResult> SelectIfNotNull<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) 
    { 
     if (source == null) return null; 
     return source.Select(selector); 
    }