2009-07-31 38 views
32

Trong another question Tôi đã hỏi, một nhận xét xuất hiện cho thấy phương pháp của khung công tác .NET Array.Copy sử dụng mã không được quản lý. Tôi đi đào với Reflector và thấy chữ ký một trong những Array.Copy quá tải phương pháp được định nghĩa như vậy:C# bên trong tĩnh extern với InternalCall thuộc tính - nội bộ hay bên ngoài?

[MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable); 

Sau khi xem xét này, tôi hơi bối rối. Nguồn gốc của sự nhầm lẫn của tôi là modifier extern có nghĩa là (MSDN link):

các modifier extern được sử dụng để khai báo một phương pháp mà được thực hiện bên ngoài.

Tuy nhiên, phương pháp kê khai cũng được trang trí với một thuộc tính MethodImplOptions.InternalCall, mà chỉ ra (MSDN link):

Chỉ định một cuộc gọi nội bộ. An cuộc gọi nội bộ là cuộc gọi đến phương thức được thực hiện trong chính thời gian chạy ngôn ngữ phổ biến .

Bất kỳ ai có thể giải thích mâu thuẫn dường như rõ ràng này không?

Trả lời

46

Tôi có thể vừa nhận xét về bài đăng leppie's nhưng đã lâu hơn một chút.

Tôi hiện đang làm việc về triển khai CLI thử nghiệm. Có nhiều trường hợp không thể triển khai phương thức tiếp xúc công khai (hoặc thuộc tính) mà không biết cách máy ảo được triển khai bên trong. Một ví dụ là OffsetToStringData, đòi hỏi kiến ​​thức về cách trình quản lý bộ nhớ phân bổ chuỗi.

Đối với các trường hợp như thế này, khi không có mã C# để thể hiện phương pháp, bạn có thể xử lý từng cuộc gọi đến phương thức theo cách đặc biệt nội bộ cho quá trình JIT. Ví dụ ở đây, thay thế mã byte call bằng ldc.i4 (số nguyên không đổi tải) trước khi chuyển nó tới trình tạo mã gốc. Cờ InternalCall có nghĩa là "Phần thân của phương thức này được xử lý theo cách đặc biệt bởi chính thời gian chạy." Có thể có hoặc có thể không phải là triển khai thực tế - trong một số trường hợp trong mã của tôi, cuộc gọi được coi là intrinsic bởi JIT.

Có những trường hợp khác mà JIT có thể có sẵn thông tin đặc biệt cho phép tối ưu hóa một phương pháp. Một ví dụ là phương pháp Math, mặc dù các số này can be implemented in C#, chỉ định InternalCall để làm cho chúng có hiệu quả nội tại có lợi ích hiệu suất đáng kể.

Trong C#, phương pháp phải có nội dung trừ khi là abstract hoặc extern. Các extern có nghĩa là một chung "Bạn có thể gọi phương pháp này từ mã C#, nhưng cơ thể của nó thực sự được xác định ở nơi khác.". Khi JIT đạt được một cuộc gọi đến phương thức extern, nó tìm kiếm nơi để tìm cơ thể và ứng xử theo những cách khác nhau cho mỗi kết quả.

  • Thuộc tính DllImport chỉ thị JIT thực hiện lệnh P/Gọi để thực thi mã gốc.
  • Cờ InternalCall hướng dẫn JIT xử lý cuộc gọi theo cách tự xác định.
  • (Có một số người khác, nhưng tôi không có ví dụ ra khỏi đỉnh đầu của tôi đối với việc sử dụng chúng.)
15

InternalCall có nghĩa là khung được cung cấp.

extern cho biết bạn không cung cấp mã.

extern có thể được sử dụng trong 2 trường hợp chung, như ở trên hoặc với p/invoke.

Với p/invoke, bạn chỉ cần nói cho phương thức nơi để thực hiện.

+0

@leppie - Tôi ước gì có thể đánh dấu cả hai bạn và câu trả lời 280Z28 như chấp nhận kể từ khi bạn' cả hai đều chính xác. Tuy nhiên, tôi cảm thấy rằng câu trả lời của 280Z28 đánh vần nó nhiều hơn một chút và giúp tôi hiểu rõ hơn, tuy nhiên, cảm ơn rất nhiều vì nỗ lực của bạn. – CraigTP

+0

Không vấn đề gì, tôi đã có đủ điểm rồi, tôi sẽ cho anh ấy thêm một số nữa :) – leppie

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