VB.NET-эквивалент для C # «динамический» с Option Strict On

69

Существует ли эквивалент для ключевого слова С# 4 'dynamic' при использовании безопасного типа VB.NET, т.е. с Option Strict On?

  • 1
    VB - безопасный тип независимо от того, включен ли параметр Option Strict включен или выключен. Прочтите о значении здесь msdn.microsoft.com/en-us/library/hbzz1a9a(VS.80).aspx
  • 0
    @jdk Хорошо, я согласен. Однако я имел в виду безопасность типов, проверенную во время компиляции, как вы уже догадались ...
Показать ещё 8 комментариев
Теги:
dynamic
option-strict

8 ответов

51
Лучший ответ

Эквивалент - объект в VB.NET, но с Option Strict Off. При Option Strict On нет эквивалента. Другими словами, ключевое слово dynamic приносит Option Strict Off эквивалентную функциональность С#.

  • 5
    За исключением того, что это не совсем то же самое. Например, я не мог понять, как динамически вызывать метод (см. Stackoverflow.com/questions/17819977/… ), как в C #.
  • 5
    Более того, модель C # позволяет вам сделать исключение для конкретного объекта, модель VB заставляет вас делать это гораздо менее детально
Показать ещё 3 комментария
38

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

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

Работает над кодом, реализованным в .NET и COM, причем последнее является наиболее распространенным. Динамическое ключевое слово в С# дало ему такую ​​же возможность. Однако он изменился в версии VB.NET версии 10, но теперь он использует DLR. Что добавляет поддержку динамической привязки к языковым реализациям, таким как Python и Ruby.

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

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

  • 13
    @Hans Passant: Я знаю, что динамика C # не совсем то же самое, что «поздняя привязка» VB. В C #, используя ключевое слово dynamic, я могу очень четко описать динамические части моей программы. Для меня это все равно, что сказать компилятору: «эй, я знаю, что я делаю для этой конкретной части моей программы». С VB.Net я должен отключить Option Strict для всего моего проекта, что может привести к незаметным ошибкам, появляющимся из-за этого.
  • 0
    @Hans @jeroen. В отредактированном коде app выводится как Object типа, поэтому использовать приложение объекта app Excel невозможно. Например, если я подставлю app.Calculate где у вас есть REM etc... он не компилируется. Я думаю, что это проблема, о которой спрашивает Йерун. Компилятор сообщает, что Error 1 Option Strict On disallows late binding.
Показать ещё 6 комментариев
6

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

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. Если я попытаюсь выполнить метод Export, таким образом:

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);

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

Хорошо, так как все работает на С#. С VB строка выглядит следующим образом:

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

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

3

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

1

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

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

0

Эквивалент ключевого слова С# dynamic в Vb.Net с опцией strict on существует в виде пакета NuGet: Dynamitey.

После установки пакета 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

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

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
0

Да, ExpandoObject.

Dim DObj = Новая система .Dynamic.ExpandoObject()

DObj.A = "abc"

DObj.B = 123

  • 1
    Кажется, что ExpandoObject использует IDictionary (Of string, object) под капотом. Интересно.
  • 0
    Вопрос спрашивает, как это сделать с помощью Option Strict On . Ваш ответ работает только с Option Strict Off

Ещё вопросы

Сообщество Overcoder
Наверх
Меню