2010-04-25 40 views
5

xem xét việc kê khai sau của một lớp tiện ích chung trong Delphi 2010:Tại sao Delphi không thể suy ra loại cho một tham số TEnumerable <T>?

TEnumerableUtils = class 
public 
    class function InferenceTest<T>(Param: T): T; 
    class function Count<T>(Enumerable: TEnumerable<T>): Integer; overload; 
    class function Count<T>(Enumerable: TEnumerable<T>; Filter: TPredicate<T>): Integer; overload; 
end; 

Bằng cách nào đó kiểu biên dịch suy luận dường như có vấn đề ở đây:

var 
    I: Integer; 
    L: TList<Integer>; 
begin 
    TEnumerableUtils.InferenceTest(I); // no problem here 
    TEnumerableUtils.Count(L);   // does not compile: E2250 There is no overloaded version of 'Count' that can be called with these arguments 
    TEnumerableUtils.Count<Integer>(L); // compiles fine 
end; 

Cuộc gọi đầu tiên làm việc như mong đợi và T là đúng được suy ra dưới dạng số nguyên.

Cuộc gọi thứ hai không hoạt động, trừ khi tôi cũng thêm <Integer> - sau đó nó hoạt động, như có thể thấy trong cuộc gọi thứ ba. Tôi đang làm điều gì đó sai hoặc là suy luận loại trong Delphi chỉ không hỗ trợ này (Tôi không nghĩ rằng đó là một vấn đề trong Java đó là lý do tại sao dự kiến ​​nó sẽ làm việc trong Delphi, quá).

Trả lời

9

Trình biên dịch sẽ cần thực hiện đối sánh mẫu để suy ra các loại thông số; nó hiện không. Trình biên dịch được giới hạn trong suy luận khá đơn giản - nếu kiểu tham số là kiểu kiểu tham số, thì trình biên dịch có thể tìm ra, nhưng không vượt quá điều đó.

Loại đối số trong ví dụ của bạn không phải là tham số kiểu đơn giản, mà là kiểu chung chung được xây dựng (nó được xây dựng với tham số kiểu của phương thức T, nhưng nó không được xây dựng ít hơn). Trình biên dịch cần thực hiện hai suy luận để tìm ra giá trị của T. Đầu tiên, nó cần phải thấy rằng kiểu generic của kiểu được xây dựng là một tổ tiên của kiểu generic của TList<T>; và nó cũng cần phải khớp với tham số kiểu T trong danh sách tham số kiểu của kiểu được xây dựng với kiểu số nguyên (Integer) trong tổ tiên của tổ tiên TList<T>.

+1

Trong trường hợp đó, nó sẽ quá khắc nghiệt để nói rằng việc thực hiện hội nghị kiểu Delphi chỉ vừa đủ tốt để đảm bảo nó được đưa vào hộp như một "tính năng mới", nhưng không thực sự đủ tốt để được xem là có ý nghĩa "tính năng hoàn thành" ? – Deltics

+1

Đôi khi "chỉ đủ tốt" thực sự không đủ tốt chút nào - tốt hơn là không có thứ gì đó hơn là có thứ gì đó không thể quack, không được đi và chỉ có thể bơi mà không bao giờ-ít đi tự gọi mình là "vịt". "Tốt hơn" trong ý nghĩa rằng nó sẽ không dẫn đến loại câu hỏi/sự nhầm lẫn đó thu hút sự chú ý đến "khoảng cách tính năng" và cho đạn cho những người tìm cách loại bỏ Delphi như một đã được/cũng chạy. Tốt hơn để nói: "loại hội nghị không ngồi thoải mái với bản chất của Pascal" - đó là, imho, một vị trí hoàn toàn đúng và hợp lệ. – Deltics

+0

Cảm ơn, Barry. Dường như tôi phải sống với nó sau đó. Có lẽ năm tới ... ;-) Một câu hỏi nhỏ liên quan nếu tôi có thể: tôi nên căn cứ vào lớp học này trên IEnumerable thay vì TEnumerable? Dường như nói chung với tôi, và sự giúp đỡ nói rằng IEnumerable không phải được khai báo trên các lớp có phương thức GetEnumerator. –

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