2012-03-15 64 views
7

我來自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 

當你使用一個,而不是其他?

回答

10

功能沒有區別,它們都返回一個基於參數的值。實際上,在編譯過程中,屬性實際上已轉換爲函數,因爲在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

5

屬性還可以有一個二傳手:

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

10

這個問題背後有很多歷史,這可以追溯到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

相關問題