Có tương đương cho từ khóa C # 4 'động' khi sử dụng loại VB.NET an toàn, tức là với Option Strict On
không?
dynamic
trong C #. Bất cứ ai đồng ý hay không đồng ý có thể bỏ phiếu hoặc nhận xét về Microsoft Connect đây
Có tương đương cho từ khóa C # 4 'động' khi sử dụng loại VB.NET an toàn, tức là với Option Strict On
không?
dynamic
trong C #. Bất cứ ai đồng ý hay không đồng ý có thể bỏ phiếu hoặc nhận xét về Microsoft Connect đây
Câu trả lời:
Tương đương là Object trong VB.NET nhưng với Option Strict Off
. Với Option Strict On
không có tương đương. Nói cách khác, từ khóa động mang lại Option Strict Off
chức năng tương đương với C #.
VB.NET luôn được tích hợp sẵn tính năng "động", ban đầu được gọi là liên kết muộn. Cú pháp này được hỗ trợ vĩnh viễn:
Dim obj = new SomeComClass()
obj.DoSomething()
Làm việc trên mã được triển khai trong .NET và COM, sau này là cách sử dụng phổ biến nhất. Các động từ khóa trong C # cho nó rằng khả năng tương tự. Nó đã được thay đổi trong VB.NET phiên bản 10, tuy nhiên, bây giờ nó cũng đang sử dụng DLR. Điều này bổ sung hỗ trợ liên kết động cho các triển khai ngôn ngữ như Python và Ruby.
Cú pháp hoàn toàn giống nhau, sử dụng từ khóa Dim mà không có As. Tuy nhiên, bạn sẽ phải sử dụng tùy chọn Tắt nghiêm ngặt, Tùy chọn Infer On có thể làm dịu cú đánh đó một chút. Nó cho thấy rằng C # sử dụng một từ khóa cụ thể để báo hiệu liên kết động là một động thái khá tốt. Afaik tất cả các yêu cầu làm như vậy trong VB.NET cũng đã được xem xét nhưng chưa được lên kế hoạch.
Nếu bạn thích Tùy chọn Nghiêm ngặt Bật thì sử dụng từ khóa Lớp Phần để bạn có thể di chuyển một số mã vào tệp nguồn khác có lẽ là cách tiếp cận hiệu quả nhất.
app
được suy ra là loại Object
, vì vậy không thể sử dụng đối tượng Ứng dụng Excel app
. Ví dụ, nếu tôi thay thế app.Calculate
nơi bạn có REM etc...
nó không biên dịch. Tôi nghĩ đây là vấn đề mà jeroen đang thắc mắc. Trình biên dịch nóiError 1 Option Strict On disallows late binding.
dynamic
. Bất cứ ai đồng ý hay không đồng ý mạnh mẽ có thể bỏ phiếu hoặc nhận xét về Microsoft Connect đây
Option
ở đầu tệp.
Điều này sẽ chứng minh những gì Basic đang nói về việc VB không có cùng mức độ chi tiết trong điều này như C #. Tôi có đoạn mã này trong C #, sử dụng sự phản chiếu để gọi động một phương thức trong thời gian chạy:
var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Lý do tôi đang làm điều này là "GetSomeData" có thể là bất kỳ phương thức nào trong số một số phương thức, mỗi phương thức nhận dữ liệu khác nhau. Phương thức nào để gọi ở đây phụ thuộc vào tham số chuỗi được truyền vào đối tượng này trong thời gian chạy, do đó, giá trị của "GetSomeData" thay đổi trong thời gian chạy.
Chữ ký của "GetSomeData" là:
public List<SomeResultSetClass> GetSomeData()
Mỗi một trong các phương thức được gọi trả về một số loại List<T>
đối tượng. Tiếp theo, tôi đang gửi đối tượng listResult đến một phương thức chung có tên là Export, trông giống như sau:
void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;
Đây là nơi chúng tôi gặp phải một vấn đề. Gọi trả về một đối tượng kiểu System.Object. Tất nhiên, a List<T>
cũng là một System.Object, nhưng giao diện được hiển thị là giao diện System.Object, không phải giao diện IList. Nếu tôi cố gắng thực hiện phương thức Export, do đó:
myExportObj.Export(listResult, parms.filePath, parms.fileType);
mã không thể biên dịch. Lỗi là:
The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Không, cám ơn!! Vấn đề là trình biên dịch không thể tìm thấy siêu dữ liệu IList, vì nó đang nhìn vào giao diện System.Object. Bây giờ, bạn có thể tạo mới List<T>
, gán (List<Whatever>) listResult
cho nó, nhưng điều đó đã đánh bại mục đích của lệnh gọi động ngay từ đầu.
Cách khắc phục là thay đổi var
thành dynamic
:
dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Vì động bỏ qua kiểm tra kiểu tĩnh tại thời điểm biên dịch, chúng tôi không gặp lỗi biên dịch. Sau đó, khi đối tượng động được chuyển đến phương thức Export, DLR (Dynamic Language Runtime) sẽ xem xét liệu nó có thể ép kiểu ngầm đối tượng để đáp ứng các yêu cầu của chữ ký phương thức hay không. Tất nhiên nó có thể.
Được rồi, đó là cách mọi thứ hoạt động trong C #. Với VB, dòng sẽ như thế này:
Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)
Với Tùy chọn Nghiêm ngặt Bật, dòng này sẽ đảo lộn trình biên dịch, như mong đợi. Với nó tắt, nó hoạt động tốt. Nói cách khác, trong VB, tôi phải tắt trình kiểm tra kiểu cho toàn bộ mô-đun có chứa dòng. Không có độ chi tiết nào tốt hơn thế.
Bạn có thể Bật tùy chọn Suy ra và Tắt tùy chọn nghiêm ngặt và vẫn có một cái gì đó rất gần.
Có đủ cách để xử lý các phương thức và thuộc tính với các đối tượng COM liên kết muộn và gõ safe ( Option Strict On
). Điều này khi sử dụng các phương pháp Microsoft.VisualBasic.Interaction.CallByName và System.Type.InvokeMember. (Hoặc tạo một tập tin "một phần" riêng biệt, nơi Option Strict
là Off
).
Nhưng để xử lý các sự kiện có ràng buộc muộn từ VB.NET không đơn giản như với kiểu động trong C #. Bạn có thể kiểm tra "hack" cho điều đó trong Sự kiện động trong VB.NET .
Tương đương với từ khóa động c # trong Vb.Net với tùy chọn nghiêm ngặt tồn tại dưới dạng gói NuGet: Dynamitey.
Sau khi cài đặt gói Dynamitey, người ta có thể viết mã Vb.Net như sau:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Dynamic.InvokeMember(o, "Substring", 5)) ' writes 67890
End Sub
End Module
Hoặc dễ đọc hơn:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
<Extension()>
Public Function Substring(self As Object, offset As Integer) As String
Return CType(Dynamic.InvokeMember(self, "Substring", offset), String)
End Function
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Substring(o, 5)) ' writes 67890
End Sub
End Module
Đã thử nghiệm với VS2017 và .net Framework 4.7.2.
Có, ExpandoObject.
Dim DObj = Hệ thống mới.Dynamic.ExpandoObject ()
DObj.A = "abc"
DObj.B = 123
Option Strict On
. Câu trả lời của bạn chỉ làm việc vớiOption Strict Off
Lưu ý rằng ngay cả với Tùy chọn nghiêm ngặt, bạn vẫn có thể sử dụng ví dụ như ExpandoObject để truy cập các thuộc tính như:
Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob