2010-05-22 118 views
64

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

+1

VB是类型安全的,无论选项严格打开还是关闭。阅读关于这里的含义http://msdn.microsoft.com/en-us/library/hbzz1a9a(VS.80).aspx – 2010-05-22 22:39:43

+0

@jdk好吧我想我必须同意。不过,我的意思是编译时检查类型安全性,因为你可能已经猜到了...... – jeroenh 2010-05-23 22:56:57

+0

@jdk:人们在谈论编程语言时使用的类型安全的定义是这样的:http://en.wikipedia.org/wiki/Type_safety – 2010-07-27 01:18:39

回答

47

相当于VB.NET中的对象,但有Option Strict Off。与Option Strict On没有相当的。换言之,dynamic关键字将Option Strict Off等效的功能带给了C#。

+5

除了它不完全一样。例如,我无法弄清楚如何在C#中动态调用方法(请参阅http://stackoverflow.com/questions/17819977/dynamic-method-calling-in-vb-without-reflection)。 – Pat 2013-07-23 20:06:04

+5

更重要的是,C#模型允许你为特定对象制定一个例外,VB模型迫使你做得不那么精细 – Basic 2014-07-16 21:34:07

+0

我知道这是一个老问题,但有一种方法可以做后期绑定和保持Option严格。从项目属性编译选项卡,我们可以将Late Binding设置为“None”(并且Option Strict采用“Custom”状态),允许在安全的环境中执行Late Binding,而不是将其设置为Off。 – Sehnsucht 2016-07-29 14:35:53

3

您可以打开选项推断和选项严格关闭,并仍然有一些非常接近。

37

VB.NET总是有内置的“动态”功能,最初称为后期绑定。此语法被永久支持:

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

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

语法完全相同,请使用Dim关键字而不使用As。然而,您将不得不使用Option Strict Off,Option Infer On可以减轻这一点。它确实表明C#使用特定的关键字来表示动态绑定是一个非常好的举措。 Afaik所有在VB.NET中都这么做的请求,目前还没有被考虑,但没有计划。

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

+12

@Hans Passant:我知道,但是C#dynamic与VB的'late binding'不太一样。在C#中,使用动态关键字我可以非常清楚地了解我的程序的动态部分。对我来说,就像告诉编译器:“嘿,我知道我正在为我的程序的这个特定部分做些什么”。随着VB.Net我必须关闭选项严格的整个项目,这可能会导致微妙的错误蔓延,因为它。 – jeroenh 2010-05-23 23:02:05

+0

@Hans @ jeroen。在你编辑的代码中,'app'被推断为'Object'类型,所以不可能*使用Excel应用程序对象'app'。例如,如果我将'app.Calculate'替换为你有'REM等...'的地方,它就不会编译。我认为这是jeroen所问的问题。编译器说'错误1选项Strict On不允许延迟绑定。“# – MarkJ 2010-08-31 12:13:41

+0

@MarkJ - 你是对的。我检查了VB.NET版本10语言规范是肯定的。令人震惊的是,DLR在任何地方都没有提及*。 Option Strict Off看起来完全不可避免。我对可怜的答案表示歉意。 – 2010-08-31 12:43:15

1

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

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

6

这将演示Basic对VB的描述,它与C#没有相同的粒度。我有这一块的C#代码,使用反射在运行时动态调用的方法:

var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null); 

我这样做的原因是,“GetSomeData”可能是任何一种方法,每获得不同的数据。在此调用的方法取决于在运行时传递给此对象的字符串参数,因此,“GetSomeData”的值在运行时会有所不同。

“GetSomeData”的签名是:

public List<SomeResultSetClass> GetSomeData() 

的方法中的每一个调用的返回某种List<T>对象。接下来,我要送的listResult对象称为导出一个通用的方法,它看起来像这样:

void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class; 

这里我们遇到了问题。 Invoke返回一个System.Object类型的对象。当然,List<T>也是一个System.Object,但暴露的接口是System。对象接口,而不是IList接口。如果我尝试执行导出方法,则:

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,但这首先破坏了动态调用的目的。

的修复方法就是改变vardynamic

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中,我必须关闭包含该行的整个模块的类型检查器。没有比这更精细的粒度。

0

是的,ExpandoObject。

昏暗DOBJ =新System.Dynamic.ExpandoObject()

DObj.A = “ABC”

DObj.B = 123

+1

ExpandoObject似乎在引擎盖下使用了一个IDictionary(字符串,对象)有趣的 – Brain2000 2017-05-08 20:16:55

+0

该问题询问如何使用Option Strict On来完成它。 'Option Strict Off' – Nick 2017-07-21 18:58:40

0

注意,即使使用选项严格上你仍然可以使用例如一个ExpandoObject来访问属性,如:

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