VB.NET等效于C#'dynamic',Option Strict On

时间:2010-05-22 22:18:52

标签: c# vb.net dynamic option-strict

使用类型安全的VB.NET时,是否有等效的C#4'dynamic'关键字,即使用Option Strict On

8 个答案:

答案 0 :(得分:51)

等效于VB.NET中的Object但带有Option Strict OffOption Strict On没有等价物。换句话说,dynamic关键字为C#带来了Option Strict Off等效功能。

答案 1 :(得分:38)

VB.NET始终具有内置的“动态”功能,最初称为后期绑定。永远支持此语法:

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

研究用.NET和COM实现的代码,后者是最常用的。 C#中的 dynamic 关键字赋予它相同的功能。它在VB.NET版本10中确实发生了变化,但它现在也在使用DLR。这增加了对Python和Ruby等语言实现的动态绑定的支持。

语法完全相同,使用不带As的Dim关键字。但是你必须使用Option Strict Off,Option Infer On可以减轻这种打击。它确实表明使用特定关键字来表示动态绑定的C#是一个非常好的举措。 Afaik所有在VB.NET中这样做的请求也已被考虑但尚未计划。

如果您更喜欢Option Strict On然后使用Partial Class关键字,那么您可以将一些代码移动到另一个源文件中,这可能是最有效的方法。

答案 2 :(得分:6)

这将说明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接口。如果我尝试执行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);

由于动态在编译时绕过静态类型检查,因此我们不会收到编译错误。然后,当动态对象传递给Export方法时,DLR(动态语言运行时)会查看是否可以隐式转换对象以满足方法签名的要求。当然可以。但

好的,这就是C#中的工作方式。使用VB,该行如下:

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

使用Option Strict On,此行会按预期方式扰乱编译器。关闭它,它工作正常。换句话说,在VB中,我必须关闭包含该行的整个模块的类型检查器。没有比这更精细的粒度。

答案 3 :(得分:3)

你可以关闭Option Infer On和Option Strict Off,但仍然有非常接近的东西。

答案 4 :(得分:1)

有足够的方法来处理具有后期绑定COM对象和类型安全(Option Strict On)的方法和属性。这在使用Microsoft.VisualBasic.Interaction.CallByName和System.Type.InvokeMember方法时。 (或创建一个单独的“部分”文件,其中Option StrictOff)。

但是处理来自VB.NET的后期绑定事件并不像C#中的动态类型那样简单。您可以在 Dynamic Events in VB.NET 中查看“hack”。

答案 5 :(得分:0)

是的,ExpandoObject。

  

Dim DObj = New System.Dynamic.ExpandoObject()

     

DObj.A =&#34; abc&#34;

     

DObj.B = 123

答案 6 :(得分:0)

请注意,即使使用Option Strict,您仍然可以使用例如一个ExpandoObject来访问以下属性:

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

答案 7 :(得分:0)

与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的测试。