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

jer*_*enh 73 c# vb.net dynamic option-strict

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

Dar*_*rov 52

相当于VB.NET中的Object但是Option Strict Off.随着Option Strict On有没有等价的.换句话说,dynamic关键字为Option Strict OffC#带来了相同的功能.

  • 除了它不完全一样.举例来说,我无法弄清楚如何动态地调用一个方法(见http://stackoverflow.com/questions/17819977/dynamic-method-calling-in-vb-without-reflection)就像你可以在C#. (5认同)
  • 更重要的是,C#模型允许您对特定对象进行异常处理,VB模型会强制您进行更细致的操作 (5认同)

Han*_*ant 38

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

 Dim obj = new SomeComClass()
 obj.DoSomething()
Run Code Online (Sandbox Code Playgroud)

研究用.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关键字,那么您可以将一些代码移动到另一个源文件中,这可能是最有效的方法.

  • @Hans Passant:我知道,但是C#dynamic与VB的'后期绑定'并不完全相同.在C#中,使用动态关键字,我可以非常清楚地了解程序的动态部分.对我而言,这就像告诉编译器:"嘿,我知道我正在为我的程序的这个特定部分做些什么".使用VB.Net,我必须为我的整个项目关闭Option Strict,这可能会因为它而导致细微的错误. (14认同)
  • @jeroenh您可以在文件级别覆盖项目级别选项,并在文件顶部使用不同的"Option"指令. (10认同)

Bob*_*des 7

这将证明Basic对VB的说法与C#不具有相同的粒度.我在C#中有这段代码,它使用反射在运行时动态调用方法:

var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Run Code Online (Sandbox Code Playgroud)

我这样做的原因是"GetSomeData"可以是多种方法中的任何一种,每种方法都获得不同的数据.在此调用哪个方法取决于在运行时传递给此对象的字符串参数,因此,"GetSomeData"的值在运行时会有所不同.

"GetSomeData"的签名是:

public List<SomeResultSetClass> GetSomeData()
Run Code Online (Sandbox Code Playgroud)

调用的每个方法都返回某种List<T>对象.接下来,我将listResult对象发送到名为Export的泛型方法,如下所示:

void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;
Run Code Online (Sandbox Code Playgroud)

这是我们遇到问题的地方.Invoke返回System.Object类型的对象.当然,a List<T>也是System.Object,但是公开的接口是System.Object接口,而不是IList接口.如果我尝试执行Export方法,那么:

myExportObj.Export(listResult, parms.filePath, parms.fileType);
Run Code Online (Sandbox Code Playgroud)

代码无法编译.错误是:

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给它,但这首先会破坏动态调用的目的.

修复方法是更改vardynamic:

dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Run Code Online (Sandbox Code Playgroud)

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

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

Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)
Run Code Online (Sandbox Code Playgroud)

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