vb.net中的参数化属性和函数之间有什么区别?

问题描述:

我来自C#世界到VB.NET,这让我感到困惑。为什么有两种方法做同样的事情?还是有一些差异,我不知道?vb.net中的参数化属性和函数之间有什么区别?

是什么下面的区别:

Public ReadOnly Property Test(ByVal v as String) As Integer 
    Get 
    Return SomeOperationOn(v) 
    End Get 
End Property 

Public Function Test(ByVal v as String) As Integer 
    Return SomeOperationOn(v) 
End Function 

当你使用一个,而不是其他?

功能没有区别,它们都返回一个基于参数的值。实际上,在编译过程中,属性实际上已转换为函数,因为在MSIL中不存在属性的概念。

语义上,但是,他们应如何使用是有区别的。属性意味着作为暴露对象内部状态的一种方式。另一方面,函数在对象的状态下操作以提供对特定问题(查询)的答案或以某种方式修改状态(命令)。

下面是一个例子:

Public Class Rectangle 
    Private _size As Size 

    ReadOnly Property Size() As Size 
     Get 
      Return _size 
     End Get 
    End Property 

    Public Function IsSquare() As Boolean 
     Return _size.Width = _size.Height 
    End Function 
End Class 

虽然Size简单地暴露所述对象的属性,所述IsSquare函数实际上为了回答一个问题对所述对象的内部状态的操作

基于这个原理,VB.NET中参数化属性最常见的用例是表示项目的序列的类,其中参数用于通过其位置访问序列中的特定元素,或者由一些独特的钥匙。换句话说,在C#中创建所谓的indexers

属性还可以有一个二传手:

Public Property Test(ByVal v as String) As Integer 
    Get 
     Return SomeDictionary(v) 
    End Get 
    Set 
     SomeDictionary(v) = Value 
    End Set 
End Property 

是有差别的,因为它可以让你写的东西是这样的:

MyObject.Test(index) = SomeValue 

C#只允许你指定这样通过属性索引:

MyOjbect[index] = SomeValue; 

这意味着,在C#中,你只能有一个每个索引属性类型。 VB.Net允许在一个类型上有多个索引属性。为了获得等价的语法,C#将直接暴露底层字典,或者如果getter/setter中有其他代码(例如日志记录),则必须创建一个附加类型来包装字典。

+0

MyOjbect [index] = SomeValue; 你可以通过vb.net的默认属性来做到这一点 – MarcelDevG 2012-03-15 22:01:45

+0

是的,你可以。你只能有一个默认属性。这使您可以在同一类型上拥有多个类似字典的属性。 – 2012-03-15 22:16:20

+0

语义,但是你不能在'ReadOnly'属性中拥有一个setter。 – 2012-03-15 22:52:33

这个问题背后有很多历史,这可以追溯到1997年,当时微软发布了COM Automation规范。其中允许属性设置者/获取者有参数。Visual Basic是该规范的早期采用者,它在很大程度上被该语言驱动,以找到VBX扩展模型的替代品。在那段时间内燃气耗尽,它严重依赖于16位编码模型。

C#团队对这个功能采取了一种非常不废话的态度,他们绝对的讨厌语法歧义。这只属于一种全新的语言。 VB.NET没有相同的奢侈品,他们不得不支持当时的上一代VB6的一些功能。

向前推进10年,C#团队不得不通过大众需求来回踩一点。索引属性在例如Office对象模型中很流行。在C#版本4中,它们允许专用于COM接口的索引属性来缓解编写C#Office代码的痛苦。此外,还增加了可选和命名参数以处理Type.Missing的苦难。而关键字动态支持后期绑定,COM和Visual Basic的另一个重要功能是真的在C#中没有这个关键字时很痛苦。

长话短说,COM是美丽的,IUnknown的优雅是鲜明的。托尼威廉斯是背后的天才。视频is here,值得一看。 COM自动化的子集IDispatch并不那么美丽。但它非常成功。语言无视它的危险。 C#没有。

这些细节可能听起来很古老,但它们并非如此。 Windows API的下一个版本WinRT完全基于IUnknown。否则称为“地铁”或“现代用户界面”。 IDispatch没有生存,取而代之的是IInspectable。

+0

在C#中,这个语法不会含糊不清,因为数组索引在C#中看起来不像使用VB中的方法调用。 – 2012-03-15 22:17:25

+0

@Joel - 有多少个索引?不止一个是平常的挂断。 worksheet.Cells [x,y]在C#版本4中受支持,对于也喜欢调用Marshal.ReleaseComObject()的程序员玩弄一个讨厌的技巧。有一个IRange接口引用是不可见的。 – 2012-03-15 22:33:39

+0

我希望语言设计者更愿意接受可以用贪婪的约束来澄清的“模棱两可”的结构。如果'Test [int]'是'Foo'类的索引属性,'Test'是普通属性,'Foo.Text [3]'将使用'Foo'的索引Test属性, (Foo.Text)[3]'会使用非索引属性'Test',然后访问默认的索引属性。不仅没有真正的歧义,而且有时'Foo.Text [3]'的含义可能很清楚,但'var blah = Foo.Text'可能不是。命名的属性允许代码允许前者禁止后者。 – supercat 2013-01-30 00:02:04