当前位置:  开发笔记 > 编程语言 > 正文

C#和VB中的VB编译器和/或IntelliSense中的错误WRT超出范围的属性设置器和ByRef fn()参数

如何解决《C#和VB中的VB编译器和/或IntelliSense中的错误WRT超出范围的属性设置器和ByReffn()参数》经验,为你挑选了1个好方法。

我已经注意到Visual Studio 2008(.NET 3.5)和Visual Studio 2010 Beta 2(.NET 4.0)中的一些看似奇怪的问题.这些问题也可能存在于先前版本中.也许它们不是问题,但不管怎样,我想在我提交Microsoft Connect报告之前看看是否有合理的解释.

安装程序(在VB中,C#结果不同,后面包含在帖子中):

Public Class SomeClass
    Public Property SomeProperty() As String
        Get
            Return String.Empty
        End Get
        Set(ByVal value As String)
        End Set
    End Property
End Class

Public Class SomeOtherClass
    Public Sub New()
        Dim sc As New SomeClass()
        Me.SomeFunction(sc.SomeProperty)
    End Sub

    ''' The param as Object fn() '''
    Public Sub SomeFunction(ByVal param As Object)
    End Sub

    ''' The param as T fn() '''
    Public Sub SomeFunction(Of T)(ByRef param As T)
    End Sub
End Class

在这种情况下,Me.SomeFunction(sc.SomeProperty)从IntelliSense的角度来看,这个调用看起来像这样:
替代文字
并且,毫不奇怪,这也是在运行时调用的.

所以,我想我的第一个问题是,为什么函数的ByRef模板化过载版本比函数的ByVal Object重载版本选择了? 我的猜测是编译器和IntelliSense只是偏向模板化版本而不是非模板化版本.在运行时,它实际上是被调用函数的ByRef模板化版本.(这不是缺陷,这只是个人想知道的问题.)

现在,对SomeProperty属性稍作修改,使得setter现在是私有的:

Public Property SomeProperty() As String
    Get
        Return String.Empty
    End Get
    Private Set(ByVal value As String)
    End Set
End Property

一旦执行此操作,就会发生以下情况Me.SomeFunction(sc.SomeProperty):
替代文字

在这种情况下,IntelliSense建议调用函数的ByVal Object重载版本,但是错误消息the 'Set' accessor of property 'SomeProperty' is not accessible表明编译器仍然期望调用ByRef模板版本.所以,这是我的第二个问题. 为什么Intellisense声称有一件事,而VB编译器显然正在尝试别的东西? 这似乎打破了我.或者我错过了什么?

如果不是打开私有的setter SomeProperty而是将属性简单地标记为ReadOnly并且删除了setter部分,那么函数的ByRef模板化版本将在IntelliSense中显示并在运行时调用(没有运行时错误).所以这引出了我的第三个问题,为什么VB编译器将ByRef params的输入处理为ReadOnly和非ReadOnly属性不同,但是在VB中有一个超出范围的setter 就SomeFunction(Of T)而言(...)在其当前范围内,该属性应该像ReadOnly一样,并且我希望它可以被调用,就好像该属性实际上是ReadOnly一样.但相反,它会产生构建错误.

与问题3相关,进行完全相同的设置(使用私有设置器),C#具有我期望的结果. 替代文字
在这里,您可以看到IntelliSense声称正在调用函数的SomeFunction(Object)重载并且没有构建错误.在运行时,实际上调用了SomeFunction(Object)版本.那么,为什么在VB.NET情况下调用的SomeFunction(Object)版本不一样呢?为什么VB.NET仍然认为需要调用SomeFunction(Of T)(ByRef T)版本?看起来IntelliSense在C#和VB.NET中正确地指出它,C#编译器正在做正确的事情,但VB.NET编译器仍然相信它应该调用ByRef模板化版本.对我来说,似乎C#编译器正在选择一个重载,而VB.NET编译器正在选择一个不同的重载,在完全相同的情况下.我错了吗?



1> Heinzi..:

关于你的第三个问题:

为什么VB编译器将ByRef参数的输入处理为ReadOnly与非ReadOnly的属性不同,但在VB中具有超出范围的setter

在CLR中,无法将属性作为ByRef传递.然而,VB.NET团队认为这将是有用的并实现了一种解决方法.在内部,

Me.SomeFunction(sc.SomeProperty)

被转换为

Dim vbTemp = sc.SomeProperty
Me.SomeFunction(vbTemp)

它被称为Do not Copy Back ByRef并用于例如Read-Only属性,或者

Dim vbTemp = sc.SomeProperty
Me.SomeFunction(vbTemp)
sc.SomeProperty = vbTemp

它被称为Copy Back ByRef,用于包含getter和setter的属性.在jaredpar的WebLog中解释了所有这些(以及一些更复杂的情况):ByRef的许多案例.

现在,您要说的是当setter超出范围时,应该执行Do not Copy Back ByRef.然而,这将导致不一致的行为:SomeFunction(sc.SomeProperty)将更新sc.SomeProperty调用时里面SomeClass,但相同的代码行会默默调用时不更新属性之外(因为二传手超出范围).


关于你的第一个和第二个问题:

为什么函数的ByRef模板化过载版本超过了函数的ByVal Object重载版本?我的猜测是编译器和IntelliSense只是偏向模板化版本而不是非模板化版本.

他们喜欢模板化的版本而不是需要扩展的版本Object.重载决策在Visual Basic语言规范的第11.8.1节中有详细描述.

为什么Intellisense声称有一件事,而VB编译器显然正在尝试别的东西?

对我来说看起来像个错误.

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有