3 Answers
3

Functionally there is no difference, they both return a value based on a parameter. In fact, properties are actually transformed into functions during compilation, since the notion of a property doesn't exist in MSIL.

Semantically, however, there is a difference in how they should be used. Properties are meant as a way to expose the internal state of an object. Functions, on the other hand, are supposed to operate on an object's state to either provide an answer to a specific question (a query) or to modify the state in some way (a command).

Here's an example:

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

While Size simply exposes a property of the object, the IsSquare function actually performs an operation on the object's internal state in order to answer a question.

Based on this principle, the most common use case for parameterized properties in VB.NET is in classes that represent a sequence of items, where the parameter is used to access a specific element in the sequence by its position or by some unique key. In other words, to create what's known as indexers in C#.

There's plenty of history behind this question, this goes back to 1997 when Microsoft released the COM Automation specification. Which allowed property setters/getters to have arguments. Visual Basic was an early adopter of the spec, it was driven in no small part by the language to find a replacement for the VBX extension model. Which ran out of gas around that time, it was heavily dependent on the 16-bit coding model.

The C# team took a pretty no-nonsense attitude to the feature, they absolute hate syntax ambiguities. That just doesn't belong in a brand new language. VB.NET didn't have the same luxury, they had to at least support some of the features of the previous generation, VB6 at the time.

Zip forward 10 years, the C# team had to back-pedal a bit by popular demand. Indexed properties are rife in, for example, the Office object model. In C# version 4 they allowed indexed properties exclusively for COM interfaces to soften the pain of writing C# Office code. And more, optional and named arguments got added as well to deal with the Type.Missing misery. And the dynamic keyword to support late binding, another important feature of COM and Visual Basic that was really painful to do in C# without that keyword.

Long story short, COM is beautiful, the elegance of IUnknown is stark. Tony Williams is the genius behind it. Video is here, much worth watching. The subset of COM Automation, IDispatch, is not so beautiful. But it was incredibly successful. Languages ignore it at their peril. C# didn't.

These details might sound arcane from a era long gone, they are not. The next version of the Windows API, WinRT is completely based on IUnknown. Otherwise known as "Metro" or "Modern UI". IDispatch did not survive, replaced by IInspectable.

In C#, this syntax would not be ambiguous because an array index doesn't look like a method call in C# like it does in VB.
–
Joel CoehoornMar 15 '12 at 22:17

@Joel - how many indexes? More than one is the usual hangup. worksheet.Cells[x, y] is supported in C# version 4, plays a nasty trick on programmers that also like to call Marshal.ReleaseComObject(). There's one IRange interface reference there that's invisible.
–
Hans PassantMar 15 '12 at 22:33

I wish language designers were more willing to accept "ambiguous" constructs which can be clarified with greedy binding. If Test[int] is an indexed property of Foo's class and Test is an ordinary property, Foo.Text[3] would use Foo's indexed Test property, while (Foo.Text)[3] would use non-indexed property Test, and then access the default indexed property of that. Not only is there no real ambiguity, but sometimes the meaning of Foo.Text[3] may be clear, but var blah = Foo.Text; may not. Named properties allow code to permit the former while forbidding the latter.
–
supercatJan 30 '13 at 0:02

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

That makes a difference, because it allows you to write something like this:

MyObject.Test(index) = SomeValue

C# only allows you to assign like that via property indexers:

MyOjbect[index] = SomeValue;

That means in C# you can only have one indexed property per type. VB.Net allows more than one indexed property on a type. To get equivalent syntax, C# would either have to expose the underlying dictionary directly or, if you have other code in the getter/setter(such as logging) you would have to create an additional type to wrap your dictionary.