使用安全VB.NET类型时,C#4'dynamic'关键字是否具有等效项Option Strict On
?
使用安全VB.NET类型时,C#4'dynamic'关键字是否具有等效项Option Strict On
?
Answers:
等效的是VB.NET中的Object,但带有Option Strict Off
。随着Option Strict On
有没有等价的。换句话说,dynamic关键字为Option Strict Off
C#带来了等效的功能。
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关键字,以便将一些代码移到另一个源文件中可能是最有效的方法。
app
推断为type Object
,因此无法使用Excel Application对象app
。例如,如果我替换app.Calculate
您拥有的位置,REM etc...
它将无法编译。我认为这是jeroen在问的问题。编译器说Error 1 Option Strict On disallows late binding.
Option
文件顶部的不同指令覆盖项目级别的选项。
这将证明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;
这是我们遇到问题的地方。调用返回类型为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接口。现在,您可以创建一个new 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,则此行会按预期使编译器不安。关闭它,它可以正常工作。换句话说,在VB中,我必须关闭包含该行的整个模块的类型检查器。没有比这更好的粒度了。
有足够的方法可以处理具有后期绑定COM对象并键入safe(Option Strict On
)的方法和属性。这在使用Microsoft.VisualBasic.Interaction.CallByName和System.Type.InvokeMember方法时。(或者创建一个单独的“部分”文件,其中Option Strict
是Off
)。
但是处理来自VB.NET的后期绑定的事件并不像使用C#中的动态类型那样简单。您可以在VB.NET的动态事件中检查“ hack” 。
与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测试。
请注意,即使启用Option Strict,您仍然可以使用例如ExpandoObject访问以下属性:
Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob