8

Vì vậy, tôi đọc Eric Lippert's 'Constraints are not part of the signature' và bây giờ tôi hiểu rằng thông số kỹ thuật chỉ định rằng các ràng buộc loại được kiểm tra Sau khi giải quyết quá tải, nhưng tôi vẫn chưa rõ lý do tại sao điều này phải đúng. Dưới đây là Eric dụ:Tại sao không phải là loại ràng buộc một phần của chữ ký phương pháp?

này không biên dịch vì có độ phân giải quá tải cho: Foo(new Giraffe()) suy luận rằng Foo<Giraffe> là trận đấu quá tải tốt nhất nhưng sau đó những hạn chế loại thất bại và một lỗi thời gian biên dịch được ném. Trong các từ của Eric:

Nguyên tắc ở đây là độ phân giải quá tải (và phương pháp kiểu suy luận) tìm thấy kết hợp tốt nhất có thể giữa danh sách đối số và danh sách các thông số chính thức của từng ứng cử viên. Đó là, họ nhìn vào chữ ký của phương pháp ứng cử viên.

Ràng buộc loại KHÔNG phải là một phần của chữ ký, nhưng tại sao chúng không thể? Một số kịch bản ở đâu là một ý tưởng tồi để xem xét các ràng buộc kiểu chữ một phần của chữ ký? Có khó khăn hay không thể thực hiện? Tôi không ủng hộ rằng nếu sự lựa chọn quá tải tốt nhất là vì bất kỳ lý do gì không thể gọi thì âm thầm dự phòng đến mức tốt nhất thứ hai; Tôi ghét điều đó. Tôi chỉ đang cố gắng hiểu tại sao các ràng buộc loại không thể được sử dụng để tác động đến việc lựa chọn tình trạng quá tải tốt nhất.

Tôi tưởng tượng rằng trong nội bộ biên dịch C#, chỉ cho mục đích giải quyết tình trạng quá tải (nó không vĩnh viễn viết lại phương pháp này), như sau:

static void Foo<T>(T t) where T : Reptile { } 

được chuyển thành:

static void Foo(Reptile t) { } 

Tại sao bạn không thể sắp xếp "kéo vào" các ràng buộc loại vào danh sách tham số chính thức? Điều này làm thay đổi chữ ký theo bất kỳ cách nào xấu? Tôi cảm thấy như nó chỉ tăng cường chữ ký. Sau đó, Foo<Reptile> sẽ không bao giờ được coi là một ứng cử viên quá tải.

Chỉnh sửa 2: Không có gì lạ khi câu hỏi của tôi quá khó hiểu. Tôi đã không đọc đúng blog của Eric và tôi đã trích dẫn ví dụ sai. Tôi đã chỉnh sửa trong ví dụ tôi nghĩ thích hợp hơn. Tôi cũng đã thay đổi tiêu đề để cụ thể hơn. Câu hỏi này dường như không đơn giản như tôi tưởng tượng đầu tiên, có lẽ tôi đang thiếu một số khái niệm quan trọng. Tôi không chắc chắn rằng đây là tài liệu stackoverflow, nó có thể là tốt nhất cho câu hỏi này/thảo luận được di chuyển ở nơi khác.

+1

Thông tin về Iguanas mà bạn trích dẫn ở đầu câu hỏi nhằm minh họa một tình huống mà suy luận kiểu * có ràng buộc trong tài khoản, cụ thể là ràng buộc trên T trong C và do đó phân giải quá tải sẽ chọn phương pháp * non generic * trong ví dụ này. Bạn có chắc chắn * đó là bit liên quan của bài viết mà bạn dự định trích dẫn để đặt câu hỏi này không? Phần còn lại của câu hỏi dường như không tuân theo logic từ nó. –

+1

Tôi nghĩ rằng bạn dự định hỏi tại sao khi gõ suy luận * thành công * nhưng gây ra một loại vi phạm ràng buộc * trên tham số kiểu phương thức *, tại sao độ phân giải quá tải không thành công khi có thay thế. Tôi đang tìm câu hỏi này rất khó hiểu, nhưng sau đó một lần nữa, nó là một phần khó hiểu của đặc điểm kỹ thuật. –

+0

Bạn nói đúng. Tôi đã đọc sai blog của bạn và sử dụng ví dụ sai. Không có thắc mắc câu hỏi của tôi đã rất bối rối. Tôi đã cố làm sáng tỏ câu hỏi của mình tốt nhất có thể; Tôi cũng sẽ đọc qua một số bài đăng trên blog khác của bạn để xem liệu tôi có thể cải thiện sự hiểu biết của mình về chủ đề này hay không. – Daryl

Trả lời

4

C# biên dịch đã không xem xét những hạn chế loại như là một phần như chữ ký phương pháp bởi vì họ không phải là một phần của phương pháp chữ ký cho CLR. Nó sẽ là thảm họa nếu độ phân giải quá tải hoạt động khác nhau đối với các ngôn ngữ khác nhau (chủ yếu là do sự ràng buộc động có thể xảy ra trong thời gian chạy và không nên khác với ngôn ngữ này, nếu không tất cả các địa ngục sẽ bị vỡ).

Tại sao nó quyết định rằng những ràng buộc này sẽ không là một phần của chữ ký phương thức cho CLR là một câu hỏi khác, và tôi chỉ có thể đưa ra những giả thuyết về thông tin đó. Tôi sẽ để mọi người biết câu trả lời đó.

+0

Nhưng điều đó chỉ thay đổi câu hỏi từ "tại sao nó không phải là một phần của C#, tại sao nó không phải là một phần của CLR" ... Có một vấn đề chính với hỗ trợ độ phân giải quá tải xem xét ràng buộc loại (xem câu trả lời của tôi) . –

+0

Có một số tính năng trong một số ngôn ngữ .Net không được thực hiện bởi các ngôn ngữ khác. Lý do chủ yếu được đưa ra là một cú pháp phụ có thể được chuyển đổi một cách trivially thành cú pháp thích hợp. Đây là một trong những cái đơn giản hơn, đơn giản là xác định phương thức gọi đến. Hơn nữa điều này khó có thể là trường hợp duy nhất có thể mơ hồ trong ngôn ngữ và không có lý do gì để trình biên dịch không đơn giản sử dụng những gì nó tìm thấy hoặc đưa ra lỗi nếu nó không thể giải quyết một cuộc gọi phương thức cụ thể. các tình huống khác. Các tính năng ngôn ngữ không phải là tính năng VM. –

0

Nếu T khớp với nhiều ràng buộc, bạn tạo sự mơ hồ không thể được giải quyết tự động. Ví dụ bạn có một lớp học chung với các hạn chế

where T : IFirst

và khác với các hạn chế

where T : ISecond

Bây giờ bạn muốn T trở thành một lớp mà thực hiện cả hai IFirstISecond.

bê tông mã ví dụ:

public interface IFirst 
{ 
    void F(); 
} 

public interface ISecond 
{ 
    void S(); 
} 

// Should the compiler pick this "overload"? 
public class My<T> where T : IFirst 
{ 
} 

// Or this one? 
public class My<T> where T : ISecond 
{ 
} 

public class Foo : IFirst, ISecond 
{ 
    public void Bar() 
    { 
     My<Foo> myFoo = new My<Foo>(); 
    } 

    public void F() { } 
    public void S() { } 
} 
+0

..Điều này gây ra xung đột tên; trong câu hỏi của tôi, lỗi là do trình biên dịch gây ra không biết quá tải phương thức nào để chọn cho phương thức gọi: 'Bar (new Iguana(), null)'. Có lẽ tôi đang chậm chạp, nhưng tôi chưa thấy sự kết nối giữa hai người này. Tôi sẽ nghiên cứu ví dụ của bạn nhiều hơn một chút .. – Daryl

+4

@EricJ bạn cũng có thể gây ra sự mơ hồ về phương pháp mà không sử dụng generics- tình huống tương tự sẽ xảy ra nếu hai lần nạp chồng của phương thức lần lượt là 'IFirst' và' ISecond'. để giải quyết phương thức nào cần gọi với đối số kiểu 'Foo'. Tôi không nghĩ rằng đây là lý do tại sao nhóm C# quyết định không làm cho nó trở thành một phần của chữ ký phương thức. –

+0

@ChrisShain Hmm, nhưng nếu bạn có sự mơ hồ cho các cuộc gọi phương thức dùng IFirst và ISecond trình biên dịch sẽ lỗi và bạn có thể khắc phục sự cố bằng cách truyền tham số đến giao diện bạn muốn. Nếu các ràng buộc chung là một phần của các chữ ký phương thức, bạn sẽ cần một cú pháp để chọn giữa các ràng buộc khác nhau tại trang gọi, và bất kỳ thay đổi nào đối với các ràng buộc chung của thư viện có nghĩa là mã gọi sẽ phải được biên dịch lại để tiếp tục làm việc. . –

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