VB.NET tương đương cho C # 'động' với Tùy chọn Nghiêm ngặt Bật


77

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 Onkhông?


1
VB là loại an toàn cho dù Tùy chọn nghiêm ngặt bật hoặc tắt. Đọc về ý nghĩa tại đây msdn.microsoft.com/en-us/library/hbzz1a9a(VS.80).aspx
John K

@jdk ok Tôi đoán tôi sẽ phải đồng ý. Tuy nhiên, ý tôi là sự an toàn của loại đã kiểm tra thời gian biên dịch, như bạn có thể đã đoán ...
jeroenh

@jdk: Định nghĩa về loại an toàn mà sử dụng tất cả mọi người khi nói về ngôn ngữ lập trình là một trong những điều này: en.wikipedia.org/wiki/Type_safety
Mauricio Scheffer

1
@jeroenh Tôi đã được truyền cảm hứng để đăng một đề xuất trên Microsoft Connect rằng sẽ rất tuyệt nếu VB có một cái gì đó giống như dynamictrong 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
MarkJ

3
Trưởng nhóm thông số kỹ thuật VB của Microsoft vừa viết blog về ý tưởng này . Đánh giá tạm thời từ nhóm VB là "VB luôn có dạng ràng buộc muộn qua Object của riêng nó. Mặc dù thật tiếc khi bạn không thể xác định phạm vi liên kết muộn của mình nhỏ hơn mức độ chi tiết của tệp, nhưng điều này dường như không phải là một vấn đề đủ lớn để biện minh cho hình thức ràng buộc muộn thứ hai. " Bạn đọc thân mến, nếu bạn cảm thấy mạnh mẽ về điều này, tại sao không để lại nhận xét trên blog hoặc về vấn đề Microsoft Connect được đề cập trong nhận xét trước đây của tôi.
MarkJ

Câu trả lời:


56

Tương đương là Object trong VB.NET nhưng với Option Strict Off. Với Option Strict Onkhông có tương đương. Nói cách khác, từ khóa động mang lại Option Strict Offchức năng tương đương với C #.


5
Ngoại trừ nó không hoàn toàn giống nhau. Ví dụ: tôi không thể tìm ra cách gọi động một phương thức (xem stackoverflow.com/questions/17819977/… ) như bạn có thể làm trong C #.
Pat

5
Thêm vào điểm, các mô hình # C cho phép bạn thực hiện một ngoại lệ cho một đối tượng cụ thể, các lực lượng mô hình VB bạn để làm điều đó ít granularly
Basic

Tôi biết đó là một câu hỏi cũ nhưng có một cách để thực hiện ràng buộc muộn và giữ Tùy chọn nghiêm ngặt. Từ các tính chất của dự án, Compile tab chúng ta có thể thiết lập Late Binding để "Không" (và Option Strict mất trạng thái "Custom") cho phép làm trễ Ràng buộc trong một môi trường an toàn hơn thiết lập nó sang Off
Sehnsucht

1
Bạn gọi động một phương thức trong vb.net trên một đối tượng chỉ bằng cách gọi nó. Tất nhiên hãy đảm bảo bao gồm dấu ngoặc đơn.
Brain2000

CallByName - có nên giúp đỡ bất kỳ người tìm kiếm web trên mạng: docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/...
ryanwebjackson

37

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.


14
@Hans Passant: Tôi biết điều đó, tuy nhiên C # động không hoàn toàn giống với 'liên kết muộn' của VB. Trong C #, với từ khóa động, tôi có thể rất rõ ràng về các phần động của chương trình của mình. Đối với tôi, nó giống như nói với trình biên dịch: "này, tôi biết tôi đang làm gì cho phần cụ thể này của chương trình của tôi". Với VB.Net, tôi phải tắt Tùy chọn nghiêm ngặt cho toàn bộ dự án của mình, điều này có thể dẫn đến các lỗi nhỏ chui vào do nó.
jeroenh

@Hans @jeroen. Trong mã đã chỉnh sửa của bạn, 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.Calculatenơ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.
MarkJ,

@MarkJ - bạn hoàn toàn đúng. Tôi đã kiểm tra Đặc tả ngôn ngữ VB.NET phiên bản 10 để chắc chắn. Đáng kinh ngạc là DLR không được đề cập ở bất cứ đâu . Tùy chọn Tắt nghiêm ngặt trông hoàn toàn không thể tránh khỏi. Tôi xin lỗi vì câu trả lời kém.
Hans Passant,

1
Tôi đã được truyền cảm hứng để đăng một gợi ý trên Microsoft Connect rằng VB nên có một cái gì đó như thế nào 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
MarkJ

11
@jeroenh Bạn có thể ghi đè các tùy chọn cấp dự án ở cấp tệp bằng các lệnh khác nhau Optionở đầu tệp.
Mark Hurd

8

Đ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>) listResultcho 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 varthà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ế.


3

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.


1

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 StrictOff).

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 .


1

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.


0

Có, ExpandoObject.

Dim DObj = Hệ thống mới.Dynamic.ExpandoObject ()

DObj.A = "abc"

DObj.B = 123


1
ExpandoObject dường như sử dụng IDictionary (Của chuỗi, đối tượng) dưới mui xe. Hấp dẫn.
Brain2000

1
Câu hỏi yêu cầu làm thế nào để làm điều đó với Option Strict On. Câu trả lời của bạn chỉ làm việc vớiOption Strict Off
Nick

0

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.