VB.NET Call Setter из Getter - PullRequest
       62

VB.NET Call Setter из Getter

0 голосов
/ 29 июля 2011

У меня есть такой класс:

Public Class MyClass

Private _intList As New List(Of Integer)
Private _avg As Decimal

Public Sub Add(ByVal anInt As Integer)
    _intList.Add(anInt)
End Sub

Public Property Avg() As Decimal
    Get
        Dim _sum As Integer = 0
        For Each anInt In _intList
            _sum += anInt
        Next
        Avg = If((_intList.Count > 0), _sum / _intList.Count, _avg)
        Return _avg
    End Get
    Set(ByVal value As Decimal)
        If _avg <> value Then
            _avg = value
            Console.WriteLine("Value changed")
        End If
    End Set
End Property

End Class

Getter вычисляет среднее значение и вызывает Setter для сохранения значения. По какой-то причине я не могу понять, среднее значение всегда равно 0. Например:

Dim c As New Class2()
c.Add(1)
c.Add(2)
c.Add(3)
Console.WriteLine(c.Avg.ToString()) ' This will print 0

Я сделал что-то не так? В чем причина этого?

Ответы [ 4 ]

6 голосов
/ 29 июля 2011

Вау, я думаю, вы обнаружили очень странное поведение VB: когда вы находитесь внутри определения функции, вы можете вернуть значение либо с помощью Return или с помощью = для «установки» значения функции.

Как это:

Function GetInteger() As Integer
    GetInteger = 5
End Function

В приведенной выше функции строка GetInteger = 5 в основном эквивалентна Return 5*.

Хорошо, значит, вы, наверное, уже это знали Но вот странная часть, и я понятия не имел, что это был случай, пока не проверил это сейчас (правда, на Mono , но я вижу то же поведение, что и вы): очевидно, это относится к добытчики недвижимости . Посмотрите на эту строку:

Avg = If((_intList.Count > 0), _sum / _intList.Count, _avg)

Вы на самом деле не вызываете установщик свойств там ; вы устанавливаете возвращаемое значение для геттера. В этом можно убедиться, убрав строку Return _avg; вдруг вы увидите, что ваш получатель начинает возвращать фактическое среднее значение.

* Не точно то же самое, как вы могли бы позже установить GetInteger на что-то другое без немедленного возврата, тогда как использование Return гарантирует, что функция сразу же вернется.

4 голосов
/ 29 июля 2011

Это специально разработано и явно упомянуто в Спецификации языка Visual Basic, глава 9.7.1:

Специальная локальная переменная, которая неявно объявляется в пространстве объявлений тела метода доступа Get с тем жеname как свойство, представляет собой возвращаемое значение свойства.Локальная переменная имеет специальную семантику разрешения имен при использовании в выражениях.Если локальная переменная используется в контексте, который ожидает выражение, которое классифицируется как группа методов, такое как выражение вызова, тогда имя разрешается в функции, а не в локальной переменной.Например:

ReadOnly Property F(i As Integer) As Integer
    Get
        If i = 0 Then
            F = 1    ' Sets the return value.
        Else
            F = F(i - 1) ' Recursive call.
        End If
    End Get
End Property

Решите проблему, непосредственно назначив поле _avg.Лучше всего избегать получения собственности с побочными эффектами.

1 голос
/ 29 июля 2011

Ваши сеттеры и геттеры действительно должны просто возвращать свойства, а не делать сами вычисления.Попробуйте создать метод, подобный calcAvg(), который выполняет средние вычисления, и на Add() вызовите этот метод (который должен внутренне не повторять весь расчет среднего, а просто обновить его. Дайте мне знать, если вы не увереныкак это сделать).Этот метод calcAvg() установит переменную экземпляра _avg.

Кроме того, я не уверен, что он действительно заставляет send иметь установщик для среднего значения.Среднее число - это производное свойство, а не то, что должно быть установлено внешним пользователем.

0 голосов
/ 29 июля 2011

Ответ MrDanA является более правильным, чем то, что я собираюсь вам дать, однако я считаю, что причина, по которой вы получаете значение 0, заключается в том, что вы никогда не устанавливаете переменную _avg в какое-либо значение. После выполнения расчета AVG, если вы делаете:

_avg = AVG вернуть _avg

Когда я это делаю, я получаю значение 2.

Как я уже говорил ранее ... Ответ MrDanA - лучший путь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...