Làm cách nào để xác định xem phương thức có cần được gọi bằng "Gọi" hoặc "Gọi điện" không?.NET CIL Call hoặc CallVirt?
Trả lời
Bạn có thể làm theo các quy tắc đơn giản từng người một để xác định mà bạn nên sử dụng:
- Là phương pháp
static
? Sau đó sử dụngcall
. - Loại bạn đang gọi trên một loại giá trị? Sau đó sử dụng
call
. (này không áp dụng nếu giá trị được đóng hộp - sau đó bạn đang thực sự gọi trênobject
hoặc một số giao diện, và đó là những loại tài liệu tham khảo.) - là phương pháp bạn đang gọi tuyên bố
virtual
hoặcabstract
? Sau đó sử dụngcallvirt
. - Bạn có gọi phương thức thông qua tham chiếu giao diện không? Sau đó sử dụng
callvirt
. - Phương pháp bạn đang gọi được khai báo là
override
, nhưng cả phương pháp và loại khai báo đều không khai báosealed
? Sau đó sử dụngcallvirt
.
Trong mọi trường hợp khác, không có công văn ảo là cần thiết, do đó bạn có thể sử dụng call
- nhưng bạn nên sử dụng callvirt
. Đây là lý do:
Sử dụng callvirt
trên phương pháp không phải ảo tương đương với call
trừ khi đối số đầu tiên là rỗng. Trong trường hợp đó, callvirt
sẽ ném một số NullReferenceException
ngay lập tức, trong khi call
thì không. Điều này có ý nghĩa, bởi vì callvirt
được thiết kế để được sử dụng trong trường hợp gửi phương thức ảo, và bạn không thể thực hiện phương thức ảo nếu bạn không có đối tượng để thực hiện tra cứu vtable.
Lưu ý rằng callvirt
sẽ vẫn ném ngoại lệ nếu đối số đầu tiên là null ngay cả khi tra cứu vtable là không cần thiết!
Xét thông tin này, sử dụng callvirt
cho tất cả các phương pháp invocations không tĩnh trên các loại tài liệu tham khảo (tùy theo từng biên dịch C# không) có thể là một lợi thế vì nó sẽ gây ra một NullReferenceException
ngay tại địa điểm cuộc gọi thay vì đôi khi sau khi this
được sử dụng (một cách rõ ràng hoặc ngầm) bên trong phương thức.
Nhưng .NET sử dụng "gọi" khi gọi một cái gì đó như Point.X. Từ những gì tôi đang đọc phương pháp loại giá trị rõ ràng sử dụng "gọi". – Will
Có, bởi vì những phương pháp đó không phải là ảo, vì vậy tôi mong đợi đầu ra sẽ sử dụng "cuộc gọi". Đọc lại câu trả lời của tôi. (Ngoài ra, cấu trúc * không thể * có các thành viên ảo vì chúng không thể được kế thừa.) – cdhowie
Điều đó có ý nghĩa, cảm ơn. Chỉ cần kỳ quặc rằng sự phản chiếu cho thấy "IsVirtual" là đúng đối với các phương thức struct. – Will
Theo mặc định, trình biên dịch C# luôn sử dụng lời gọi cho mọi thứ ngoại trừ các cuộc gọi kiểu tĩnh hoặc giá trị. Điều này gây ra việc kiểm tra null ngầm định đối số 'this' (arg0). Bạn không bắt buộc phải tuân theo quy ước này, nhưng mọi phương thức ảo trên một kiểu tham chiếu chắc chắn sẽ yêu cầu callvirt.
Ngoại trừ các phương pháp ảo trên các lớp được niêm phong. –
Nếu bạn sử dụng cuộc gọi trong dynamicmethod trên một phương pháp ảo thời gian chạy ném một ngoại lệ bảo mật.
- 1. Thao tác .NET CIL của ngăn xếp đánh giá
- 2. Ưu điểm của kiến thức CIL trong .NET
- 3. Lập trình CIL
- 4. Trình xây dựng chuỗi trong CIL (MSIL)
- 5. erlang call stack
- 6. Cách chèn mã CIL vào C#
- 7. Hành vi ủy nhiệm của CIL với xung đột "tĩnh" của phương pháp đích
- 8. Ruby: ProC# call vs yield
- 9. Hiểu phương pháp Ruby #call
- 10. Cài đặt AssemblyFileVersion với MSBuild-call?
- 11. Fatal error: Call to undefined function oci_connect()
- 12. Tránh .call() và .apply() sử dụng .bind()
- 13. Viết trình biên dịch cho .net - IL hoặc Bytecode?
- 14. Sự khác nhau giữa CIL và MSIL (IL) là gì?
- 15. WCF: Per-Call và Per-Session dịch vụ ... cần thuyết phục rằng Per-Call là đáng giá
- 16. Lỗi khi sử dụng .Call() trong R 3.0. +
- 17. CIL OpCode (Ldarg_0) được sử dụng mặc dù không có đối số
- 18. Cuộc gọi AJAX .NET đến ASMX hoặc ASPX hoặc ASHX?
- 19. .NET hoặc PHP, công ty hoặc nguồn mở?
- 20. Angular JS hủy $ http call trước khi gọi $ http
- 21. MiniProfiler Hiển thị Asp.Net Mvc Slow Call Actions Thỉnh thoảng
- 22. Cách tạo ngôn ngữ .Net hoặc JVM?
- 23. MathML hoặc OMML đến PNG w/.NET?
- 24. .NET Dictionary: nhận hoặc tạo mới
- 25. C# hoặc .NET Flushing Keyboard Buffer
- 26. VSS hoặc SVN cho dự án .Net?
- 27. Singleton Per Call Context (Yêu cầu Web) trong Unity
- 28. Fatal error: Call to openssl_random_pseudo_bytes chức năng không xác định()
- 29. Tạo Call-Tree từ cơ sở dữ liệu cscope
- 30. Fatal error: Call to Phương pháp xác định DateTime :: createfromformat()
Điều này phải làm gì với C#? – SLaks