2013-05-24 12 views
5

Tôi gặp một scenerio trong đó một kiểu giá trị đang triển khai ref. kiểu.Làm thế nào một loại giá trị có thể thực hiện kiểu ref

Chỉ muốn biết làm thế nào mà là có thể (những gì diễn ra đằng sau những cảnh?)

Một struct là một loại giá trị và giao diện một ref. nhưng một cấu trúc có thể triển khai giao diện mà không có bất kỳ lỗi nào ...

Bất kỳ suy nghĩ nào? Cảm ơn trước

Trả lời

9

Thực ra, nó thực hiện theo hai cách khác nhau cùng một lúc.

Thứ nhất, bất kỳ loại giá trị nào cũng có thể được đóng hộp thành một thể hiện đối tượng được nhập tham chiếu. Hộp này được phát minh bởi thời gian chạy theo yêu cầu và sẽ triển khai giao diện theo cách bạn mong đợi - tức là hộp sẽ triển khai bất kỳ giao diện nào thực hiện loại giá trị.

Tuy nhiên, CLI cũng cho phép "cuộc gọi bị hạn chế". Một cuộc gọi bị hạn chế biến một cuộc gọi ảo thành một cuộc gọi tĩnh nhưng chỉ chính xác với kịch bản mà một kiểu giá trị thực hiện một phương thức thể hiện bằng cách ghi đè hoặc thực hiện giao diện (nếu không nó được thực hiện bởi JIT như một cuộc gọi ảo). Trong generics cụ thể làm cho việc sử dụng rộng rãi của các cuộc gọi bị hạn chế (opcode hạn chế đã được thêm vào cùng một lúc như generics, vì lý do chính xác này).

+0

+1, bạn đã đúng. Tôi đã cung cấp các ví dụ, nhưng không giải thích tại sao. – Gjeltema

+2

@Gjeltema Tôi hy vọng sẽ truyền cảm hứng cho bạn để thêm chi tiết, không phải để xóa câu trả lời của bạn: ( –

+0

Vâng, tôi có thể đã thêm chi tiết hơn - nhưng bạn đã trả lời nó, vì vậy dường như không có nhiều điểm. :) Đừng lo - tôi sẽ sống để trả lời một ngày khác. – Gjeltema

2

Giao diện không phải là loại tham chiếu, đó chỉ là hợp đồng về cách triển khai loại.

Biến của loại giao diện phải là tham chiếu, vì loại triển khai giao diện có thể là loại tham chiếu. Biến của loại giao diện phải có khả năng chứa loại tham chiếu hoặc loại giá trị vì cả hai có thể triển khai giao diện. Một loại giá trị có thể được đóng hộp để nó được tham chiếu, nhưng một loại tham chiếu không thể được "làm phẳng" thành một giá trị.

+0

Điều gì làm phẳng * nghĩa là ở đây ..? –

+0

@KenKin: Vâng ... phẳng ... Nó được cho là mô tả cách một loại tham chiếu sẽ được biến thành một loại giá trị, nhưng nó không có bất kỳ ý nghĩa chính xác nào, vì điều đó là không thể. – Guffa

+0

Oh .. cảm ơn bạn. Tôi vẫn khó hiểu. Vì tôi không chắc chắn * làm phẳng * có nghĩa là một sự chuyển đổi hoặc đấm bốc, hoặc là một trong hai và bao gồm bất kỳ cách nào khác? –

1

Mặc dù tất cả chúng ta sử dụng loại từ để tham chiếu đến giao diện, và thậm chí tài liệu MSDN mô tả giao diện là loại tham chiếu, giao diện không phải là Kiểu giống như bất kỳ loại tham chiếu nào khác hoặc bất kỳ loại giá trị nào . Đó là, trong một ý nghĩa rất thực tế không phải là một loại ở tất cả. Nó là một hợp đồng cho một hành vi (một tập các phương thức, các thuộc tính và các sự kiện) mà một kiểu phải chứa bởi đã được khai báo để thực hiện giao diện đó.

public interface ITestInterface { } 
public class MyClass:ITestInterface { } 

ITestInterface m = new MyClass() as ITestInterface; 
var t = m.GetType(); 

Bạn sẽ thấy rằng mặc dù biến m được tuyên bố là loại ITestInterface, Type biến t vẫn là MyClass. Vì vậy, mặc dù, vì lý do lịch sử chúng tôi sử dụng từ loại để áp dụng cho giao diện, "loại" của giao diện là một điều rất khác nhau là loại đối tượng cụ thể, là một thể hiện của một lớp hoặc cấu trúc.

trích dẫn từ Essential Net Don Box của

Các CLR giao dịch với các đối tượng và giao diện kiểu khác so với tiền nhiệm của nó (C++ và COM). Trong C++ và COM, một loại bê tông cụ thể có một bảng phương thức cho mỗi loại cơ sở hoặc giao diện được hỗ trợ. Trong độ tương phản , một loại bê tông nhất định trong CLR có chính xác một phương pháp bảng. Theo suy luận, một đối tượng dựa trên CLR có chính xác một loại xử lý. Điều này tương phản hoàn toàn với C++ và COM, trong đó đối tượng sẽ thường có một vptr cho mỗi loại hoặc giao diện cơ sở. Vì lý do này, của CLR castclass không dẫn đến giá trị con trỏ thứ hai trong số tương tự như của C++ dynamic_cast hoặc số Query-Interface của COM.

Đọc điều này rõ ràng là bản thân giao diện không bao giờ có bảng vptr hoặc CORINFO_CLASS_STRUCT như các đối tượng cụ thể thực sự (các loại tham chiếu và giá trị) có thể có. Cấu trúc này được tạo và duy trì bởi CLR cho mỗi Kiểu được nạp bởi mã thực thi khi chạy. Một lần nữa, từ Essential Net,

Các CORINFO_CLASS_STRUCT chứa các con trỏ tới hai bảng mô tả tất cả các giao diện kiểu hỗ trợ. Các mã vạch isinstcastclass [CLR] sử dụng một trong các bảng này để xác định xem loại có hỗ trợ giao diện được cho là hay không. Thứ hai trong số các bảng này là một bảng bù giao diện mà CLR sử dụng khi gửi các cuộc gọi phương thức ảo được thực hiện đối với các tham chiếu đối tượng dựa trên giao diện.

Như có thể thấy rõ ràng từ các tham chiếu này, giao diện là một loại điều cơ bản khác với loại tham chiếu (lớp) hoặc loại giá trị (cấu trúc). Mỗi đối tượng (kiểu tham chiếu) hoặc kiểu giá trị được khởi tạo hoặc được sử dụng bên trong .Net phải là một cá thể cụ thể của một lớp hoặc một cấu trúc. Và mọi đối tượng hoặc cấu trúc được nạp bởi CLR đều có tham chiếu đến một CORINFO_CLASS_STRUCT được tạo ra cho kiểu cụ thể của lớp hoặc cấu trúc đó. Intefaces là các loại của các kiểu, được định nghĩa để đảm bảo rằng bất kỳ lớp hoặc cấu trúc nào được khai báo trong danh mục đó (được khai báo để thực hiện giao diện đó), phải chứa một thành viên kiểu (phương thức, thuộc tính, sự kiện, v.v.) cho mỗi thành viên được khai báo trong định nghĩa giao diện.

0

Giao diện không phải là loại theo nghĩa là các lớp và cấu trúc! Giao diện không tồn tại một mình; do đó, chúng không phải là loại tham chiếu cũng như loại giá trị. Bạn có thể gán null cho một tham chiếu. Nhưng nếu loại trình triển khai là loại giá trị, khi bạn chỉ định một biến loại đó cho loại khác, thì nó hoạt động giống như một loại giá trị. Và do đó, nó hoạt động giống như một loại tham chiếu cho các loại tham chiếu.

Lớp và cấu trúc là các loại dữ liệu (mã) nhưng giao diện là loại cho các loại. Chúng có thể được sử dụng để phân loại các loại khác. Chúng buộc các loại khác theo một giao thức và không có gì hơn. Họ chỉ là một cách bố trí, một định nghĩa, một hợp đồng; không phải là một thứ hiện có.

+0

Giao diện chắc chắn là Loại. Có sự khác biệt giữa một biến thuộc loại 'Danh sách ' hoặc 'IList '. Sau này có thể tham chiếu đến một thể hiện cùng loại như trước đây, nhưng tham chiếu (như biến đó) vẫn sẽ được đánh máy như một giao diện. –

+0

Tôi không nói rằng họ không phải là loại. Và loại cơ sở của một giao diện không phải là System.Object như vậy: "Giao diện không phải là loại trong một cảm giác rằng các lớp và cấu trúc là"; "Lớp và cấu trúc là các loại cho dữ liệu (mã) nhưng giao diện là loại cho các loại". –