80

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

4

8 回答 8

59

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

于 2010-05-22T22:37:58.350 回答
38

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

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

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

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

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

于 2010-05-22T22:49:27.637 回答
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 类型的对象。当然aList<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 中,我必须关闭包含该行的整个模块的类型检查器。没有比这更精细的粒度了。

于 2014-07-28T23:36:20.330 回答
3

您可以打开 Option Infer On 和 Option Strict Off 并且仍然有一些非常接近的东西。

于 2010-05-22T22:40:11.307 回答
1

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

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

于 2013-03-18T05:24:45.913 回答
1

Vb.Net 中带有选项 strict 的 c# 动态关键字的等效项以 NuGet 包的形式存在:Dynamitey。

install-package 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 测试。

于 2018-08-10T08:43:49.373 回答
0

是的,ExpandoObject。

暗 DObj = 新 System.Dynamic.ExpandoObject()

DObj.A = "abc"

DObj.B = 123

于 2017-02-16T18:28:46.153 回答
0

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

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
于 2018-01-17T18:56:58.620 回答