2009-02-28 20 views
11

Điều quan trọng nhất bạn biết về generics là gì: tính năng ẩn, lỗi phổ biến, thực hành hữu ích nhất và hữu ích nhất, mẹo ...Những điều quan trọng nhất về C# generics ... bài học kinh nghiệm

Tôi bắt đầu thực hiện hầu hết của thư viện/API của tôi bằng cách sử dụng Generics và muốn thu thập các mẫu, mẹo, v.v ... phổ biến nhất, được tìm thấy trong thực tế.

Hãy để tôi chính thức hóa câu hỏi: Điều quan trọng nhất bạn đã học về Generics là gì?

Hãy cố gắng cung cấp những ví dụ - nó sẽ được dễ dàng hơn để hiểu, như trái ngược với giới thiệu phức tạp và quá khô

Cảm ơn

Câu hỏi này có phần tương tự như Jon's question, tuy nhiên, trên một chủ đề khác nhau.

+0

cộng đồng wiki ?! –

+0

Đây phải là CW –

+0

Đồng ý với Afshari: Bất kỳ câu trả lời được chấp nhận nào cũng sẽ là sự kết hợp của các bài đăng khác nhau và phải là wiki'd cho mục đích đó. Bỏ phiếu để đóng cho đến khi đây là trường hợp; ưa thích theo dõi câu hỏi. –

Trả lời

14

Một trong những điều quan trọng nhất mà tôi đã học được là bạn có thể constrain the generic type parameter(s). Điều này có thể rất mạnh mẽ, cho phép bạn tùy chỉnh lớp cho chỉ một số loại đối tượng nhất định và cho phép bạn sử dụng các thành viên của loại đó trong lớp chung của bạn. Tôi nhận ra rằng điều này khá cơ bản, nhưng đó là một trong những thứ làm cho generics vô cùng hữu ích.

3

Hiểu các khả năng và hạn chế của suy luận kiểu chung trong C#. Hiểu sâu về những gì trình biên dịch có thể và không thể suy ra dựa trên (ví dụ) các loại tham số trong phương pháp của bạn có thể được tận dụng để làm cho các trường hợp sử dụng phổ biến của API của bạn dễ đọc hơn.

+1

xin vui lòng cung cấp một ví dụ .... Tôi muốn nhìn thấy nó trong hành động –

+0

Hầu hết LINQ là một ví dụ, thực sự. :) Tấn API chung, nhưng lưu ý rằng bạn hầu như không bao giờ phải chỉ định một loại khi sử dụng nó. –

3

Bài học quan trọng nhất về generics tôi đã học được là: bạn càng sử dụng chúng càng tốt.

0

Trước hết nó là không quan trọng để biết cách hoạt động của Generics trong C#. Điều này article cung cấp cho bạn một cái nhìn tổng quan tốt về Generics của Anders Hejlsberg (Người cha của C#). Tôi không nghĩ rằng việc sử dụng chúng thường xuyên nhất có thể là tốt. Sử dụng Generics khi họ thực sự có ý nghĩa. Luôn luôn nhớ KISS và YAGNI (Giữ nó đơn giản ngu ngốc; Bạn không cần nó) từ lập trình cực đoan.

0

Loại đại biểu chung luôn là loại bất biến.

Tôi gặp phải sự cố tương tự với nội dung được nêu trong liên kết bên dưới ngày khác và điều này gây ra một số nhầm lẫn vì tôi không hiểu tại sao tôi phải truyền bộ sưu tập của mình.

http://www.theserverside.net/blogs/thread.tss?thread_id=47323

4

Mỗi chuyên môn hóa của một kiểu generic được coi là một loại độc đáo khi nói đến những thứ như các thành viên tĩnh.Ví dụ, với loại này:

class GenericType<T> 
{ 
    public static int SomeValue; 
} 

Các khẳng định thành công nếu chúng ta làm điều này:

GenericType<int>.SomeValue = 3; 
Debug.Assert(GenericType<double>.SomeValue == 0); 

Điều này là do:

typeof(GenericType<int>) != typeof(GenericType<double>) 

Mặc dù

typeof(GenericType<int>.GetGenericTypeDefinition() == typeof(GenericType<double>).GetGenericTypeDefinition() 
1

Don 't biết nếu họ là quan trọng nhất, nhưng tôi đã đã học được những điều sau đây:

Generics sẽ chỉ có thể nhận được thông qua phản ánh nếu bạn không biết loại frikkin. Trong một số trường hợp, bạn có thể cần các giao diện không chung chung để sử dụng các lớp chung của bạn trong các tình huống mà kiểu không xác định.

Tôi gần như đắm đầu tôi cho đến khi tôi grocked rằng

public class Foo<T> where T : Foo<T> { 
    public T CloneMe() ... 
} 

là hoàn toàn mã hợp lệ và cho phép lớp cơ sở của bạn để lộ phương pháp và tài sản liên quan đến lớp chuyên ... mà kết thúc trong một định nghĩa của một máy trạng thái dọc theo các trạng thái:

public abstract class Machine<S,M> where S : State<S,M> where M : Machine<S,M> { 
    protected S state; 
} 

public abstract class State<S,M> where S : State<S,M> where M : Machine<S,M> { 
    protected M machine; 
} 

Generics có thể hơi khó sử dụng. Ngày hôm kia tôi đã này:

List<Tuple<Expression<Func<DataTable,object>>,Expression<Func<DataTable,object>>>> 

phew ...

+0

Nội dung hay - hãy tiếp tục! –

+0

Đối với đoạn mã cuối cùng, tôi đã có một cái gì đó rất giống nhau một vài tháng trước đây. Tôi refactored nó vào một cái gì đó một litle đơn giản hơn và dễ đọc mặc dù. – dotnetdev

+0

@GSS - Đó là những gì tôi đã làm. Nó chỉ là không thể đọc được. Tôi bắt nguồn từ Tuple cho việc này. Chỉ cần bây giờ tôi tái cấu trúc nó một lần nữa bởi vì nó chỉ ra rằng lớp cần thêm ngữ nghĩa :) Đó là một cuộc sống buồn cười để trở thành một nhà phát triển, luôn luôn movin '! – flq

1
MyGeneric<T> where T : IComparable 

không làm

MyGeneric<IComparable> 

một lớp cơ sở của nó.

+0

Tốt nhất, mặc dù tôi đã học được nó, ban đầu, từ C++ –

1

Tôi đã học được rằng generics là công cụ mạnh mẽ không rõ nhưng lạm dụng dẫn đến mã rất khó đọc.

2

Không hiệp phương sai hoặc đối xứng (ít nhất trong 3.5). Hãy nhận biết điều này khi thiết kế hệ thống phân cấp lớp bao gồm các tham số kiểu chung.

+1

Nó cuối cùng ở đây, em bé! Cũng lưu ý rằng CLR đã có một số hỗ trợ cho điều này (với + và - chú thích trong IL), nhưng các ngôn ngữ và trình biên dịch đã không cung cấp cú pháp cho nó. –

+0

Tôi đã thực sự thất vọng về phương sai được giới thiệu. Tôi nghĩ rằng có gì là tốt, nhưng không đi đủ xa. –

2

Hai bài học thú vị. Đầu tiên; với danh sách; cố gắng suy nghĩ theo số T; for full details see here, nhưng trong ngắn hạn, bạn cần phải sử dụng:

public void Foo<T>(IList<T> data) where T : SomeBaseClassOrInterface {} 

và không:

public void Foo(IList<SomeBaseClassOrInterface> data) {} 

Thứ hai: watch for the edge cases ;-p

Bạn có thấy cái bẫy ở đây?

static void Foo<T>() where T : new() 
{ 
    T t = new T(); 
    Console.WriteLine(t.ToString()); // works fine 
    Console.WriteLine(t.GetHashCode()); // works fine 
    Console.WriteLine(t.Equals(t)); // works fine 

    // so it looks like an object and smells like an object... 

    // but this throws a NullReferenceException... 
    Console.WriteLine(t.GetType()); // BOOM!!! 
} 
+0

Đánh dấu, giải thích phần bùng nổ? Có phải do thực tế rằng T có thể là một loại giá trị - và GetType KHÔNG có sẵn cho nó? –

+0

xem liên kết 'watch for the edge cases' – johnc

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