VB.NET эквивалент для C # «динамический» с Option Strict On - PullRequest
71 голосов
/ 23 мая 2010

Есть ли эквивалент для динамического ключевого слова C # 4 при использовании типа safe VB.NET, то есть с Option Strict On?

Ответы [ 8 ]

51 голосов
/ 23 мая 2010

Эквивалентом является Object в VB.NET, но с Option Strict Off. С Option Strict On нет эквивалента. Иными словами, ключевое слово dynamic приносит Option Strict Off эквивалентную функциональность C #.

38 голосов
/ 23 мая 2010

В VB.NET всегда была встроена «динамическая» функция, изначально называемая поздним связыванием. Этот синтаксис был поддержан навсегда:

 Dim obj = new SomeComClass()
 obj.DoSomething()

Работал над кодом, реализованным в .NET и COM, причем последний является наиболее распространенным. Ключевое слово dynamic в C # дало ему такую ​​же возможность. Это изменилось в VB.NET версии 10, однако теперь оно также использует DLR. Который добавляет поддержку динамического связывания для языковых реализаций, таких как Python и Ruby.

Синтаксис точно такой же, используйте ключевое слово Dim без As. Однако вам придется использовать Option Strict Off, Option Infer On может немного смягчить этот удар. Это действительно показывает, что C # использование определенного ключевого слова для обозначения динамического связывания было довольно хорошим ходом. На данный момент все запросы на это в VB.NET уже рассмотрены, но не запланированы.

Если вы предпочитаете Option Strict On, то использование ключевого слова Partial Class, чтобы вы могли переместить часть кода в другой исходный файл, вероятно, является наиболее эффективным подходом.

6 голосов
/ 29 июля 2014

Это продемонстрирует, что Basic говорит о том, что VB не имеет такой же степени детализации в этом, как C #. У меня есть этот кусок кода в C #, который использует отражение для динамического вызова метода во время выполнения:

var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);

Причина, по которой я это делаю, заключается в том, что GetSomeData может быть любым из нескольких методов, каждый из которых получает разные данные. Какой метод вызывать здесь, зависит от строкового параметра, передаваемого в этот объект во время выполнения, поэтому значение «GetSomeData» изменяется во время выполнения.

Подпись "GetSomeData":

public List<SomeResultSetClass> GetSomeData()

Каждый из вызванных методов возвращает некоторый объект List<T>. Затем я отправляю объект listResult в универсальный метод с именем Export, который выглядит следующим образом:

void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;

Здесь мы сталкиваемся с проблемой. Invoke возвращает объект типа System.Object. Конечно, List<T> также является System.Object, но представленный интерфейс - это интерфейс System.Object, а не интерфейс IList. Если я попытаюсь выполнить метод экспорта, таким образом:

myExportObj.Export(listResult, parms.filePath, parms.fileType);

код не компилируется. Ошибка:

The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Нет, спасибо !! Проблема в том, что компилятор не может найти метаданные IList, потому что он смотрит на интерфейс System.Object. Теперь вы можете создать новый List<T>, присвоить ему (List<Whatever>) listResult, но это в первую очередь противоречит цели динамического вызова.

Исправлено изменение var на dynamic:

dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);

Поскольку динамический обход статической проверки типов во время компиляции, мы не получаем ошибку компиляции. Затем, когда динамический объект передается методу Export, DLR (Dynamic Language Runtime) проверяет, может ли он неявно привести объект в соответствие требованиям сигнатуры метода. Что, конечно, может.

Хорошо, вот как все работает в C #. С VB строка выглядит так:

Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)

При Option Strict On эта строка расстраивает компилятор, как и ожидалось. С ним все нормально работает. Другими словами, в VB я должен отключить проверку типов для всего модуля, который содержит строку. Нет более тонкой детализации, чем эта.

3 голосов
/ 23 мая 2010

Вы можете включить Option Infer On и Option Strict Off и все еще иметь что-то очень близкое.

1 голос
/ 18 марта 2013

Существует достаточно способов обработки методов и свойств с поздним связыванием COM-объектов и типом safe (Option Strict On). Это при использовании методов Microsoft.VisualBasic.Interaction.CallByName и System.Type.InvokeMember. (Или создайте отдельный «частичный» файл, где Option Strict равно Off).

Но обрабатывать события с поздним связыванием из VB.NET не так просто, как с динамическим типом в C #. Вы можете проверить «взлом» для этого в Динамические события в VB.NET .

0 голосов
/ 10 августа 2018

В пакете NuGet существует эквивалент динамического ключевого слова c # в Vb.Net с параметром строго по:

После установки пакета Dynamitey можно написать код Vb.Net следующим образом:

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

Или чуть более читабельный:

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

Протестировано с VS2017 и .net Framework 4.7.2.

0 голосов
/ 17 января 2018

Обратите внимание, что даже с Option Strict вы можете использовать, например, ExpandoObject для доступа к таким свойствам, как:

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
0 голосов
/ 16 февраля 2017

Да, ExpandoObject.

Dim DObj = Новая System.Dynamic.ExpandoObject ()

DObj.A = "abc"

DObj.B = 123

...