2011-11-08 23 views
7

Có thể triển khai một lớp được ràng buộc với hai tham số chung duy nhất không?Một lớp học chung với hai loại không độc nhất (duy nhất)

Nếu không, có phải vì nó chưa được thực hiện hoặc không thể cho cấu trúc ngôn ngữ (thừa kế) không?

Tôi muốn một cái gì đó có dạng:

class BidirectionalMap<T1,T2> where T1 != T2 
{ 
    ... 
} 

Tôi đang thực hiện một Bidirectional dictionary. Đây chủ yếu là một câu hỏi về sự tò mò, không cần thiết.


Được diễn giải từ các ý kiến:

  1. Dan: "hậu quả tiêu cực là gì nếu ràng buộc này không được đáp ứng"

  2. Tôi: "Sau đó, người dùng có thể lập chỉ mục với bản đồ [t1] và bản đồ [t2]. Nếu họ cùng loại, sẽ không có sự phân biệt và sẽ không có ý nghĩa gì".

  3. Dan: Trình biên dịch thực sự cho phép [hai tham số kiểu chung để xác định các quá tải phương thức riêng biệt], vì vậy tôi tò mò; tùy ý chọn một trong các phương thức để gọi?

+1

Bạn luôn có thể ném một 'mới ShouldBeCompileTimeError()' trong hàm tạo . :-) – foson

+1

có lẽ bởi vì nó không có ý nghĩa, chúng là generics, một cái gì đó mà không nên "bị ràng buộc" bởi các loại. – GriffinHeart

+0

Vì tò mò, hậu quả tiêu cực là gì nếu hạn chế này không được đáp ứng? Một ánh xạ giữa các đối tượng từ cùng một bộ là một yêu cầu rất phổ biến. –

Trả lời

4

Mở rộng trên ví dụ để làm nổi bật vấn đề:

public class BidirectionalMap<T1,T2> 
{ 
    public void Remove(T1 item) {} 
    public void Remove(T2 item) {} 

    public static void Test() 
    { 
     //This line compiles 
     var possiblyBad = new BidirectionalMap<string, string>(); 

     //This causes the compiler to fail with an ambiguous invocation 
     possiblyBad.Remove("Something"); 
    } 
} 

Vì vậy, câu trả lời là, ngay cả khi bạn không thể xác định các hạn chế T1 = T2, nó không quan trọng, bởi vì trình biên dịch sẽ thất bại ngay sau khi bạn cố gắng làm điều gì đó sẽ vi phạm ràng buộc tiềm ẩn. Nó vẫn bắt được sự thất bại trong thời gian biên dịch, vì vậy bạn có thể sử dụng những tình trạng quá tải này với khả năng miễn dịch. Đó là một chút kỳ lạ, vì bạn có thể tạo một thể hiện của bản đồ (và thậm chí có thể viết mã IL thao tác bản đồ một cách thích hợp), nhưng trình biên dịch C# sẽ không cho phép bạn tàn phá bằng cách tùy ý giải quyết quá tải không rõ ràng.


Một lưu ý phụ là loại quá tải này có thể gây ra một số hành vi lạ nếu bạn không cẩn thận. Nếu bạn có một BidirectionalMap<Animal, Cat> và Cát: Động vật, xem xét những gì sẽ xảy ra với mã này:

Animal animal = new Cat(); 
map.Remove(animal); 

này sẽ gọi quá tải mà sẽ đưa động vật, vì vậy nó sẽ cố gắng để loại bỏ một chìa khóa, mặc dù bạn có thể đã có ý định loại bỏ giá trị Cat. Đây là một trường hợp hơi nhân tạo, nhưng nó đủ để đảm bảo thận trọng khi các hành vi rất khác nhau xảy ra do hậu quả của quá tải phương thức. Trong những trường hợp như vậy, có thể dễ dàng đọc và duy trì hơn nếu bạn chỉ cung cấp cho các phương thức tên khác nhau, phản ánh các hành vi khác nhau của chúng (RemoveKey và RemoveValue, giả sử.)

+0

Câu trả lời gốc tuyệt vời! Lỗi văn bản:' Cuộc gọi không rõ ràng giữa các phương thức hoặc thuộc tính sau: BidirectionalMap . this [T] 'và' BidirectionalMap . this [K] '" – user664939

0

Ràng buộc loại có vẻ như một từ khóa sai. Trong khi họ làm contrain những gì các tham số kiểu là, mục đích là để cho trình biên dịch biết những gì hoạt động có sẵn cho các loại.
Nếu bạn muốn, bạn có thể có một ràng buộc trong đó T1 và T2 đều xuất phát từ các lớp cơ sở bê tông riêng biệt, nhưng tôi không nghĩ đó là điều bạn muốn.

-1

Không có cách hiệu quả để thực hiện việc này mà không áp đặt bất kỳ hạn chế nào khác đối với các loại đó. Như một người khác đã lưu ý, bạn có thể tạo ra những ràng buộc rằng hai loại này bắt nguồn từ hai lớp cơ sở khác nhau, nhưng đó có lẽ không phải là rất tốt từ quan điểm thiết kế.

Đã chỉnh sửa để thêm: lý do không được triển khai rất có thể vì không ai ở Microsoft coi như là cần thiết để thực thi tại thời gian biên dịch, không giống như các ràng buộc khác liên quan đến cách bạn thực sự có thể để sử dụng các biến của các loại được chỉ định. Và như một số nhà bình luận đã chỉ ra, bạn chắc chắn có thể thực thi điều này khi chạy.

0

Sự bất bình đẳng sẽ không giúp trình biên dịch bắt lỗi. Khi bạn chỉ định các ràng buộc về các tham số kiểu, bạn đang nói với trình biên dịch rằng các biến kiểu này sẽ luôn luôn hỗ trợ một giao diện nhất định hoặc sẽ hoạt động theo những cách nhất định. Mỗi người trong số đó cho phép trình biên dịch xác nhận một cái gì đó giống như "phương pháp này sẽ có mặt để nó có thể được gọi trên T".

Sự bất bình đẳng của các thông số loại sẽ giống như việc xác thực các đối số phương thức đó không phải là rỗng. Nó là một phần của logic của chương trình, không phải là loại an toàn của nó.

0

Tôi không hoàn toàn chắc chắn lý do tại sao đây sẽ là một kiểm tra thời gian biên dịch mong muốn. Nó sẽ có thể cơ bản bằng cách vượt qua các điều kiện bằng cách đấm bốc hoặc là chìa khóa hoặc giá trị, do đó làm cho việc kiểm tra thời gian biên dịch vô ích.

Một số xem xét cần được thực hiện để xác định ... tôi đang cố gắng ngăn chặn những lỗi nào?

Nếu bạn chỉ đơn giản là dừng một đồng nghiệp lười biếng không đọc tài liệu, hãy thêm séc chỉ gỡ lỗi và ném ngoại lệ. Bằng cách này, séc có thể được xóa cho mã phát hành, ví dụ:

#if Debug 

if (T1 is T2 || T2 is T1) 
{ 
    throw new ArguementException(...); 
} 

#endif 

Nếu bạn đang cố gắng để ngăn chặn một người ác độc từ việc sử dụng thư viện của bạn một cách ngoài ý muốn, thì có lẽ một tấm séc runtime là cần thiết, nếu không nó sẽ dễ dàng để hộp khóa hoặc giá trị.

+0

Bạn cũng có thể đặt kiểm tra này trong hàm dựng tĩnh của kiểu generic Vì vậy, nó sẽ chỉ chạy một lần. (Kiểm tra của bạn sẽ không biên dịch, bởi vì bên trái của toán tử 'is' có tham chiếu đối tượng, không phải là tên kiểu. Bạn muốn' if (typeof (T1) = = typeof (t2) ') – phoog

0

Không, bạn không thể sử dụng bình đẳng (hoặc bất bình đẳng) làm hạn chế. Nói một cách đơn giản, bình đẳng không phải là một ràng buộc, mà là một điều kiện. Bạn nên kiểm tra điều kiện chẳng hạn như bình đẳng hoặc bất bình đẳng của các loại trong hàm tạo và ném một ngoại lệ thích hợp.

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