带有Option Strict On的C#“动态”的VB.NET等效项


76

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


1
VB是安全类型,无论Option Strict on On还是Off。在此处阅读有关含义的信息msdn.microsoft.com/zh-cn/library/hbzz1a9a(VS.80).aspx
John K 2010年

@jdk好吧,我想我必须同意。但是,正如您可能已经猜到的,我的意思是编译时检查的类型安全性……
jeroenh,2010年

@jdk:每个人都在谈论编程语言时使用的类型安全的定义是这样的:en.wikipedia.org/wiki/Type_safety
Mauricio Scheffer

1
@jeroenh我受到启发在Microsoft Connect上发布了一个建议,那就是如果VBdynamic在C#中具有类似功能,那将是很好的。任何人谁同意不同意或者可以投票或发表评论,微软连接在这里
MarkJ

3
微软VB规范负责人刚刚在博客上发表了这个想法。VB团队的临时评估是:“ VB始终通过Object拥有自己的形式后期绑定。虽然您不能将后期绑定的范围定为小于文件粒度,这是一个遗憾,但这似乎不是一个足够大的问题为第二种形式的后期装订辩护。” 亲爱的读者,如果您对此有强烈的兴趣,为什么不对博客或我先前的评论中提到的Microsoft Connect问题发表评论。
MarkJ 2011年

Answers:


54

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


5
除了不完全一样。例如,我不知道如何像在C#中那样动态地调用方法(请参阅stackoverflow.com/questions/17819977/…)。
2013年

5
更重要的是,在C#模式可以让你破例为特定对象,你做它的VB模型的力量远不如精细地
基本

我知道这是一个老问题,但是有一种方法可以进行后期绑定并保持Option Strict。从项目属性的“编译”选项卡中,我们可以将“后期绑定”设置为“无”(并且Option Strict的状态为“自定义”),这允许在比设置为“关”更安全的环境中进行后期绑定
Sehnsucht

1
您可以通过在对象的vb.net中动态调用方法。确保包括括号。
Brain2000 '17

CallByName-应该可以帮助任何网络搜索者: docs.microsoft.com/zh-cn/dotnet/visual-basic/programming-guide/…–
ryanwebjackson

37

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关键字,以便将一些代码移到另一个源文件中可能是最有效的方法。


14
@Hans Passant:我知道,但是C#动态与VB的“后期绑定”并不完全相同。在C#中,使用dynamic关键字可以非常明确地了解程序的动态部分。对我来说,这就像告诉编译器:“嘿,我知道我在程序的这一特定部分正在做什么”。使用VB.Net,我必须为我的整个项目关闭Option Strict,这可能会导致潜入细微的错误。
jeroenh 2010年

@Hans @jeroen。在您编辑的代码中,app推断为type Object,因此无法使用Excel Application对象app。例如,如果我替换app.Calculate您拥有的位置,REM etc...它将无法编译。我认为这是jeroen在问的问题。编译器说Error 1 Option Strict On disallows late binding.
MarkJ 2010年

@MarkJ-您绝对正确。我检查了VB.NET版本10语言规范以确保。令人震惊的是,在任何地方都没有提到DLR 。Option Strict Off看起来是完全不可避免的。我为不好的回答道歉。
汉斯·帕桑

1
我受到启发,在Microsoft Connect上发布了一个建议,即VB应该有类似的东西dynamic。任何人谁同意不同意或强烈地可以投票或评论在这里微软连接
MarkJ

11
@jeroenh您可以在文件级别使用Option文件顶部的不同指令覆盖项目级别的选项。
马克·赫德

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;

这是我们遇到问题的地方。调用返回类型为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给它,但这首先破坏了动态调用的目的。

解决方法是更改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,则此行会按预期使编译器不安。关闭它,它可以正常工作。换句话说,在VB中,我必须关闭包含该行的整个模块的类型检查器。没有比这更好的粒度了。


3

您可以打开“选项推断”和“严格关闭选项”,但仍有一些内容非常接近。


1

有足够的方法可以处理具有后期绑定COM对象并键入safe(Option Strict On)的方法和属性。这在使用Microsoft.VisualBasic.Interaction.CallByName和System.Type.InvokeMember方法时。(或者创建一个单独的“部分”文件,其中Option StrictOff)。

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


1

与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测试。


0

是的,ExpandoObject。

昏暗的DObj =新的System.Dynamic.ExpandoObject()

DObj.A =“ abc”

DObj.B = 123


1
ExpandoObject似乎在后台使用了IDictionary(string,object)。有趣。
Brain2000

1
问题要求如何处理Option Strict On。您的答案仅适用于Option Strict Off
Nick

0

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

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.