2009-07-27 26 views
6

Tôi có một lớp sưu tập với phương thức Bằng mà tôi muốn chuyển vào một phương thức để thực hiện kiểm tra bình đẳng giữa mỗi mục. Hơn nữa, tôi muốn cho phép các loại đại biểu để hoạt động trên superclasses của T cũng như T bản thân:Tôi có thể chỉ định mối quan hệ 'siêu kiểu' trong các ràng buộc chung của C# không?

public delegate bool EqualityComparer<T>(T x, T y); 

public class Collection<T> 
{ 
    //... 

    public bool Equals<U>(Collection<T> other, EqualityComparer<U> eq) where T : U 
    { 
     // code using eq delegate to test equality between 
     // members of this and other collection 
    } 
} 

Thật không may, trình biên dịch borks trên này ('Collection.Equals()' không xác định tham số kiểu 'T '). Có cách nào xác định loại ràng buộc/hoạt động này không?

Trả lời

4

Không, tôi e rằng bạn không thể chỉ định ràng buộc như thế. (Tôi đã muốn nó quá dịp.)

Bạn thể viết một phương pháp chung tĩnh với hai tham số gõ vào một lớp học không chung mặc dù:

public delegate bool EqualityComparer<T>(T x, T y); 

public class Collection 
{ 
    public static Equals<T, U>(Collection<T> first, 
           Collection<T> second, 
           EqualityComparer<U> comparer) where T : U 
    { 

    } 
} 

và bạn thậm chí có thể thực hiện cuộc gọi một phương pháp dụ trên lớp generic nếu bạn thích:

// Implementing the static method: 
return first.Equals(second, new EqualityComparer<T>(comparer)); 

nơi phương pháp dụ của bộ sưu tập sẽ chỉ được:

public bool Equals(Collection<T> other, EqualityComparer<T> eq) 
{ 
    // ... 
} 

Điều này sử dụng contravariance có sẵn cho tạo đại biểu từ C# 2 trở đi.

+0

Có ý nghĩa để có thể không? Sẽ không làm cho nó có thể bởi suy luận khó bởi vì hai khai báo có thể được lan truyền trong toàn bộ dự án, hoặc thậm chí không được chỉ định – Dykam

+1

Vâng, nó có ý nghĩa hoàn hảo - bạn có thể chỉ định rằng tham số kiểu phải là * phân lớp * của một cái gì đó khác, vậy tại sao không phải là cách khác vòng? (Java cho phép điều này, sử dụng 'T super Foo' thay vì' T mở rộng Foo', btw.) –

+0

Ah - Tôi thấy bạn đang chỉnh sửa câu trả lời của bạn để đặt những gì tôi đã viết như một người lái :) – ShuggyCoUk

0

Nếu bạn rõ ràng muốn tham số kiểu là một lớp kế thừa của U, bạn không cần generics, mà đúng hơn là sử dụng U làm kiểu tham số chính thức. Và có polimorfism đá trong! :)

1

Như Jon đã nói, bạn không thể tham chiếu T trong giới hạn theo cách đó vì nó được khai báo ở cấp lớp.

Nếu bạn có thể viết phương pháp này không được tiếp cận đến trạng thái riêng của bộ sưu tập (hoặc với họ là nội bộ) sau đó bạn có thể viết lại như sau:

public class Collection<T> 
{ 
    ... 
} 

public static class CollectionExtentions 
{ 
    public static bool Equals<T,U>(
      this Collection<T> first, 
      Collection<T> other, 
      EqualityComparer<U> eq) where T : U 
    { 
      ... // legal to use eq here on the T values with collections 
    } 
} 

Ngẫu nhiên tôi đề nghị bạn sử dụng Func<T,T,bool> chứ không phải của riêng bạn có tên là đại biểu

+0

Đây là trong .NET 2, vì vậy Func không có sẵn: ( – thecoop

+0

Ah - downer :(bạn có thể muốn thêm người đó vào câu hỏi (vì rõ ràng bạn sẽ không thể sử dụng cú pháp của phương thức mở rộng để đề xuất của Jon của phương thức tĩnh được sử dụng bởi phương thức cá thể là tốt nhất) – ShuggyCoUk

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