2010-06-08 20 views
5

Trong Tuple, nếu bạn có nhiều hơn 7 mục, bạn có thể cung cấp mục thứ 8 là một bộ khác và xác định tối đa 7 mục và sau đó là một bộ khác làm thứ 8 và trên và trên xuống dòng. Tuy nhiên, không có ràng buộc về mục thứ 8 tại thời gian biên dịch. Ví dụ: đây là mã pháp lý cho trình biên dịch:Tại sao lệnh kiểm tra trong Tuple <T1... TRest> không bị hạn chế?

var tuple = new Tuple<int, int, int, int, int, int, int, double> 
       (1, 1, 1, 1, 1, 1, 1, 1d); 

Mặc dù tài liệu intelliSense nói rằng TREST phải là Tuple. Bạn không nhận được bất kỳ lỗi nào khi viết hoặc xây dựng mã, nó không biểu hiện cho đến khi chạy theo dạng của một ArgumentException.

Bạn có thể khoảng triển khai một Tuple sau vài phút, hoàn thành với mục thứ 8 bị ràng buộc bởi Tuple. Tôi chỉ tự hỏi tại sao nó lại được thực hiện hiện tại? Có thể đó là vấn đề tương thích về phía trước, nơi họ có thể thêm nhiều yếu tố hơn với giả thuyết C# 5?

phiên bản ngắn của thô thực hiện

interface IMyTuple { } 

class MyTuple<T1> : IMyTuple 
{ 
    public T1 Item1 { get; private set; } 
    public MyTuple(T1 item1) { Item1 = item1; } 
} 

class MyTuple<T1, T2> : MyTuple<T1> 
{ 
    public T2 Item2 { get; private set; } 
    public MyTuple(T1 item1, T2 item2) : base(item1) { Item2 = item2; } 
} 

class MyTuple<T1, T2, TRest> : MyTuple<T1, T2> where TRest : IMyTuple 
{ 
    public TRest Rest { get; private set; } 
    public MyTuple(T1 item1, T2 item2, TRest rest) 
     : base(item1, item2) 
    { 
     Rest = rest; 
    } 
} 

...

var mytuple = new MyTuple<int, int, MyTuple<int>> 
       (1, 1, new MyTuple<int>(1)); // legal 
var mytuple2 = new MyTuple<int, int, int>(1, 2, 3); // illegal at compile time 
+0

Thật sao? Làm thế nào một người có thể thực hiện điều đó sao cho phần tử cuối cùng bị ràng buộc là một 'Tuple' có kích thước bất kỳ mà không định nghĩa một lớp cơ sở bổ sung hoặc giao diện phổ biến trong các kích thước' Tuple' chung khác nhau? Tôi không thấy làm thế nào bạn nghĩ rằng họ có thể làm điều đó trong C#. – mquander

+1

@mquander, Tuple triển khai ITuple. Bạn có thể định nghĩa kiểu Tuple (MyTuple) của riêng bạn để ràng buộc mục cuối cùng với một giao diện (IMyTuple) và bạn nhận được một kiểm tra thời gian biên dịch. –

+2

Ồ, tôi không biết về 'ITuple'. Cảm ơn vì sự đúng đắn của bạn. Tôi lưu ý rằng 'ITuple' là nội bộ; có lẽ họ muốn giữ nó bên trong - nếu nó là một ràng buộc ở đây, nó sẽ phải được công khai. – mquander

Trả lời

1

Các giả thuyết ITuple hạn chế sẽ không thực sự hạn chế đó là một tuple [1], sẽ nó ? Chỉ là một lớp thực hiện ITuple.

[1] - Tôi đang xác định "tuple" là một trong các lớp học Tuple<> do BCL cung cấp.

+0

Đó là một điểm thú vị. Bạn nói đúng, bất kỳ kiểu cũ nào cũng có thể thực hiện giao diện (bất kể cái gì đòi hỏi) và đáp ứng yêu cầu của ràng buộc. Nhưng sau đó tôi đoán nó cũng đặt ra câu hỏi về lý do tại sao hạn chế loại trong thời gian chạy, bạn có thể thả một Tuple vào bất kỳ một trong các khe hiện có, chỉ cần nói "chúng tôi đang làm một lớp chung 8 rãnh (tối đa), sử dụng nó như bạn thấy phù hợp. " –

+1

Đó là cách duy nhất để thực sự hạn chế nó thành một bộ (kiểm tra thời gian chạy cho một giao diện 'nội bộ', vì vậy chúng tôi không thể thực hiện nó). Các khe cuối cùng thực sự không phải là một tuple vì nó ảnh hưởng đến việc thực hiện 'Kích thước',' GetHashCode', 'ToString', vv Nó được xử lý hoàn toàn khác so với các khe khác. –

7

Đó là một hạn chế của hệ thống kiểu. ITuple là giao diện nội bộ. Nếu nó là một ràng buộc chung chung, nó sẽ cần phải được công khai, sau đó sẽ cho phép mọi người thực hiện ITuple của riêng mình mà không thể có bất cứ điều gì để làm với tuples. Việc giới hạn nó vào bên trong cho phép đội ngũ BCL đảm bảo rằng nó thực sự là một loại tuple, nhưng kết quả là an toàn hơn một chút so với thời gian biên dịch có thể.

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