使用类型安全的VB.NET时,是否有等效的C#4'dynamic'关键字,即使用Option Strict On
?
答案 0 :(得分:51)
等效于VB.NET中的Object但带有Option Strict Off
。 Option 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 Strict
为Off
)。
但是处理来自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的测试。