web-dev-qa-db-ja.com

Option Strict OnのC# 'dynamic'に相当するVB.NET

タイプセーフVB.NETを使用する場合、つまりOption Strict Onを使用する場合、C#4の 'dynamic'キーワードに相当するものはありますか?

73
jeroenh

同等のものはVB.NETのObjectですが、Option Strict OffOption Strict On同等のものはありません。別の言い方をすれば、 dynamic キーワードはOption Strict Off C#と同等の機能。

52
Darin Dimitrov

VB.NETには、元々遅延バインディングと呼ばれていた「動的」機能が常に組み込まれていました。この構文は永久にサポートされていました。

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

.NETおよびCOMで実装されたコードで作業しました。後者が最も一般的な使用方法です。 C#のdynamicキーワードは、同じ機能を提供しました。 VB.NETバージョン10では変更されましたが、現在はDLRも使用しています。 PythonやRubyなどの言語実装に動的バインディングのサポートを追加します。

構文はまったく同じです。AsなしでDimキーワードを使用します。ただし、Option Strict Offを使用する必要があります。OptionInfer Onは、その打撃を少し弱めることができます。特定のキーワードを使用して動的バインディングを通知するC#が非常に良い動きであることを示しています。 Afaikは、VB.NETでも同様にこれを行うためのすべてのリクエストをまだ検討していますが、計画していません。

Option Strict Onを使用したい場合は、Partial Classキーワードを使用して、コードの一部を別のソースファイルに移動するのがおそらく最も効果的なアプローチです。

38
Hans Passant

これは、BasicがVB 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ですが、公開されているインターフェイスはIListインターフェイスではなくSystem.Objectインターフェイスです。 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.

結構です!!問題は、コンパイラがSystem.Objectインターフェイスを参照しているため、IListメタデータが見つからないことです。これで、新しいList<T>、 割り当てます (List<Whatever>) listResultそれに、しかしそれはそもそも動的呼び出しの目的を無効にします。

修正は、vardynamicに変更することです:

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では、行を含むモジュール全体の型チェッカーをオフにする必要があります。それより細かい粒度はありません。

7
BobRodes

Option Infer OnとOption Strict Offをオンにしても、非常に近いものを使用できます。

3
Joel Coehoorn

メソッドとプロパティをレイトバインディングCOMオブジェクトとタイプセーフ(Option Strict On)。これは、Microsoft.VisualBasic.Interaction.CallByNameおよびSystem.Type.InvokeMemberメソッドを使用する場合。 (または、別の「部分的な」ファイルを作成します。Option StrictOffです)。

ただし、VB.NETからの遅延バインディングを使用してイベントを処理することは、C#の動的な型ほど簡単ではありません。 VB.NETの動的イベントで「ハック」を確認できます。

1
Vozzie

Vb.Netのc#ダイナミックキーワードと同等のオプション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

Option Strictがオンの場合でも、たとえば次のようなプロパティにアクセスするためのExpandoObject

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

はい、ExpandoObject。

Dim DObj =新しいSystem.Dynamic.ExpandoObject()

DObj.A = "abc"

DObj.B = 123

0
Doron Saar