В чем разница между параметризованным свойством и функцией в 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

Когда вы используете один, а не другой?

Ответ 1

Функционально нет разницы, они оба возвращают значение, основанное на параметре. Фактически, свойства фактически преобразуются в функции во время компиляции, так как понятие свойства не существует в 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 является класс, представляющий последовательность элементов, где этот параметр используется для доступа к определенному элементу в последовательности по его положению или по каким-то уникальным ключ. Другими словами, чтобы создать то, что известно как indexers на С#.

Ответ 2

За этим вопросом много истории, это относится к 1997 году, когда Microsoft выпустила спецификацию COM Automation. Который позволил разработчикам/получателям свойств иметь аргументы. Visual Basic была ранним усыновителем спецификации, она была в немалой степени изменена языком, чтобы найти замену модели расширения VBX. В течение этого времени у него не было газа, он сильно зависел от 16-битной модели кодирования.

Команда С# приняла довольно нелепое отношение к этой функции, они несовместимы с синхронностью синтаксиса ненависти. Это просто не относится к совершенно новому языку. У VB.NET не было такой же роскоши, они должны были хотя бы поддерживать некоторые функции предыдущего поколения, VB6 в то время.

Вперед вперед 10 лет команде С# пришлось немного потренироваться по популярному спросу. Индексированные свойства распространены, например, в объектной модели Office. В версии С# 4 они разрешали индексированные свойства исключительно для интерфейсов COM, чтобы смягчить боль при написании кода С# Office. И еще, дополнительные и именованные аргументы также добавились, чтобы справиться с печалью Type.Missing. И динамическое ключевое слово для поддержки позднего связывания, еще одна важная функция COM и Visual Basic, которая была очень болезненна в С# без этого ключевого слова.

Короче говоря, COM красив, элегантность IUnknown безупречна. Тони Уильямс - гений, стоящий за ним. Видео здесь, стоит посмотреть. Подмножество COM Automation, IDispatch, не так красиво. Но это было невероятно успешным. Языки игнорируют это на свой страх и риск. С# - нет.

Эти детали могут звучать тайно от давно ушедшей эпохи, но это не так. Следующая версия Windows API, WinRT полностью основана на IUnknown. В противном случае он известен как "Метро" или "Современный интерфейс". IDispatch не сохранился, заменен на IInpectable.

Ответ 3

Свойство также может иметь сеттер:

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

С# позволяет только назначать это посредством индексаторов свойств:

MyOjbect[index] = SomeValue;

Это означает, что в С# вы можете иметь только одно индексированное свойство для каждого типа. VB.Net позволяет использовать более одного индексированного свойства для типа. Чтобы получить эквивалентный синтаксис, С# либо должен был бы напрямую использовать базовый словарь, либо, если у вас есть другой код в getter/setter (например, ведение журнала), вам нужно будет создать дополнительный тип для вашего словаря.