Еквівалент VB.NET для C # "динамічний" з опцією Strict On


77

Чи існує еквівалент для ключового слова C # 4 "динамічний" при використанні безпечного типу VB.NET, тобто з Option Strict On?


1
VB є безпечним для типу, незалежно від того, чи ввімкнено, чи вимкнено опцію Строгий. Про значення читайте тут msdn.microsoft.com/en-us/library/hbzz1a9a(VS.80).aspx
John K

@jdk добре, мабуть, доведеться погодитися. Однак я мав на увазі перевірений під час компіляції тип безпеки, як ви могли здогадатися ...
jeroenh

@jdk: визначення безпеки типу, яке всі використовують, говорячи про мови програмування, є таким: en.wikipedia.org/wiki/Type_safety
Маурісіо Схеффер

1
@jeroenh Мене надихнуло опублікувати пропозицію на Microsoft Connect, що було б непогано, якби VB мав щось подібне dynamicдо C #. Той, хто погоджується чи не погоджується, може тут проголосувати чи прокоментувати Microsoft Connect
MarkJ

3
Провідний спеціаліст Microsoft VB щойно писав про цю ідею . Попередня оцінка від команди VB: "VB завжди мав власну форму з пізнім прив'язуванням через Object. Хоча це ганьба, що ви не можете застосувати свою пізню прив'язку менше, ніж деталізація файлів, це не здається досить великою проблемою щоб виправдати другу форму пізнього зв’язку ". Шановний читачу, якщо ви відчуваєте глибоке ставлення до цього, чому б не залишити коментар у блозі чи проблемі Microsoft Connect, згаданій у моєму попередньому коментарі.
MarkJ

Відповіді:


56

Еквівалентом є Object у VB.NET, але з Option Strict Off. При Option Strict Onцьому немає еквівалента. Іншими словами, динамічне ключове слово забезпечує Option Strict Offеквівалентну функціональність C #.


5
Хіба що це не зовсім однаково. Наприклад, я не міг зрозуміти, як динамічно викликати метод (див. Stackoverflow.com/questions/17819977/… ), як це можна в C #.
Пет

5
До речі, модель C # дозволяє зробити виняток для конкретного об'єкта, модель VB змушує робити це набагато менш детально
Basic

Я знаю, що це давнє запитання, але є спосіб зробити пізнє прив’язування та дотримання строгості варіанту. За допомогою властивостей проекту, вкладки «Компіляція», ми можемо встановити для «Пізнє прив’язування» значення «Немає» (і Опція «Строгий» прийняти стан «Спеціальний»), що дозволяє виконувати «Пізнє прив’язування» в більш безпечному середовищі, ніж встановити значення «Вимкнено»
Sehnsucht,

1
Ви динамічно викликаєте метод у vb.net на об'єкті, просто викликаючи його. Обов’язково додайте дужки.
Brain2000

CallByName - Має допомогти будь-якому веб- пошукачу
ryanwebjackson

37

У VB.NET завжди була вбудована "динамічна" функція, яку спочатку називали пізнім прив'язуванням. Цей синтаксис підтримувався назавжди:

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

Працював над кодом, реалізованим у .NET та COM, останній найбільш поширений. Динамічний ключове слово в C # дав йому той же потенціал. Це було змінено у версії VB.NET 10, однак, зараз він також використовує DLR. Що додає підтримку динамічного прив’язки до таких реалізацій мови, як Python та Ruby.

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

Якщо ви віддаєте перевагу Option Strict On, тоді використання ключового слова Partial Class, щоб ви могли перемістити частину коду в інший вихідний файл, є, мабуть, найбільш ефективним підходом.


14
@Hans Passant: Я знаю, що, однак, динаміка C # не зовсім така, як "пізнє прив'язування" VB. У C # за ключовим словом динамічний я можу бути дуже чітким щодо динамічних частин моєї програми. Для мене це все одно, що сказати компілятору: "Гей, я знаю, що я роблю для цієї конкретної частини моєї програми". За допомогою VB.Net я повинен вимкнути Option Strict для всього мого проекту, що може призвести до того, що через це закрадаються тонкі помилки.
jeroenh

@Hans @jeroen. У відредагованому коді appвиводиться як тип Object, тому не можна використовувати об’єкт програми Excel app. Наприклад, якщо я підставляю, app.Calculateде у вас є, REM etc...він не компілюється. Я думаю, що це проблема, про яку задається Джерон. Компілятор кажеError 1 Option Strict On disallows late binding.
MarkJ

@MarkJ - Ви абсолютно праві. Я перевірив специфікацію мови VB.NET версії 10, щоб переконатися. Вражаюче DLR ніде не згадується . Варіант Strict Off виглядає абсолютно неминучим. Прошу вибачення за погану відповідь.
Ганс Пассант,

1
Я був натхненний розмістити пропозицію на Microsoft Connect, що VB повинен мати щось на зразок dynamic. Той, хто погоджується або не погоджується, може тут проголосувати чи прокоментувати Microsoft Connect
MarkJ

11
@jeroenh Ви можете замінити параметри рівня проекту на рівні файлу за допомогою різних Optionдиректив у верхній частині файлу.
Mark Hurd

8

Це продемонструє, що 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. Звичайно, a 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);

Оскільки динамічний режим обходить перевірку статичного типу під час компіляції, ми не отримуємо помилки компіляції. Потім, коли динамічний об’єкт переходить до методу експорту, DLR (Dynamic Language Runtime) перевіряє, чи може неявно передавати об’єкт відповідно до вимог підпису методу. Що, звичайно, може.

Гаразд, так це працює в C #. У VB лінія виглядає так:

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

З Option Strict On цей рядок засмучує компілятор, як і очікувалося. Якщо його вимкнути, він працює нормально. Іншими словами, у VB я повинен вимкнути перевірку типу для всього модуля, що містить рядок. Немає більш тонкої деталізації, ніж ця.



1

Існує достатньо способів обробляти методи та властивості з пізньо прив’язуваними COM-об’єктами та типом safe ( Option Strict On). Це при використанні методів Microsoft.VisualBasic.Interaction.CallByName та System.Type.InvokeMember. (Або створіть окремий "частковий" файл там, де Option Strictє Off).

Але обробляти події з пізнім прив'язуванням з VB.NET не так просто, як з динамічним типом в C #. Ви можете перевірити "хак" для цього в Динамічні події у VB.NET .


1

Еквівалент динамічного ключового слова c # у Vb.Net із строкою опцією 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

Так, ExpandoObject.

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

DObj.A = "abc"

DObj.B = 123


1
Схоже, що ExpandoObject використовує IDictionary (з рядка, об'єкта) під капотом. Цікаво.
Brain2000

1
Питання задає питання, як це зробити Option Strict On. Ваша відповідь працює лише зOption Strict Off
Ніком

0

Зверніть увагу, що навіть якщо увімкнено Option Strict, ви все одно можете використовувати, наприклад, ExpandoObject для доступу до таких властивостей, як:

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.