C #: разумная альтернатива необязательному параметру в свойстве? - PullRequest
1 голос
/ 07 ноября 2010

Дано: класс со свойствами типа SomeNumber, которые внутренне могут быть нулевыми (то есть int?), но внешне вы обычно не хотите обрабатывать этот особый случай и притворяетесь, что они начинаются как ноль. До сих пор мы всегда возвращаем ненулевую версию, т.е. int. Я хотел бы добавить опцию, чтобы иметь пустую версию.

Самый простой вариант: Два свойства. Прекрасно работает, но, к сожалению, загромождает класс множеством избыточных опций. Внешний код:

return myObject.SomeNumber; // Not nullable.
return myObject.SomeNumber_Nullable; // Nullable.

Внутренне грязный, но внешне приятный вариант: Свойство с необязательным параметром. Я еще не узнал, как это сделать в C #; .NET Reflector, по-видимому, пропускает неправильный код. В VB.NET это выглядит так:

Private _SomeNumber As Nullable(Of Integer)
Public Property SomeNumber(Optional ByVal AllowNull As Boolean = False) As Nullable(Of Integer)
  Get
    If Not AllowNull AndAlso _SomeNumber Is Nothing
      Return 0
    End If

    Return _SomeNumber
  End Get
  Set(ByVal value As Boolean)
    _SomeNumber = value
  End Set
End Property

Внешний код:

return myObject.SomeNumber; // Not nullable.
return myObject.SomeNumber(true); // Nullable.

Из недостатков: * Реализация C # такая уродливая .NET Reflector, похоже, даже не знает, как это сделать, * Я нахожу общее представление о параметризованных свойствах сомнительным, * В необнуляемом примере возвращаемый тип не соответствует фактическому поведению свойства - теперь компилятор считает, что может быть null, но на самом деле не может.

Есть еще идеи?

Ответы [ 2 ]

3 голосов
/ 07 ноября 2010

Звучит так, будто вы пытаетесь переоценить свой класс.Свойство имеет значение null или его нет, и клиент не обязан проверять наличие нулей.Мне было бы больно понимать ваш API, что для меня звучит примерно так: «Это свойство никогда не равно нулю.Если только вы не проверите, чтобы узнать, действительно ли оно нулевое.Да?

Кроме того, попытка скрыть нулевые значения обычно является плохой идеей, поскольку она скрывает ошибки в вашей программе.

1 голос
/ 07 ноября 2010

Свойства не могут иметь параметры в C #, поэтому, если вы хотите использовать синтаксис свойств, вам понадобятся два свойства с разными именами.

Если вы не хотите, чтобы пользователи вашего класса знали о том, что внутренне ваше поле может быть пустым, это довольно просто, если вы контролируете реализацию своего свойства. Определите вспомогательное поле вашей собственности типа int?, но оставьте тип вашей собственности как int.

Например:

private int? _someNumber = null;

public int SomeNumber { 
  get { return _someNumber.HasValue ? _someNumber.Value : 0; }
  set { _someNumber = value; }
}

Теперь внутри вы всегда можете получить доступ к _someNumber.HasValue, чтобы проверить, установлено или нет значение.

Однако, когда вы говорите: «Я хотел бы добавить опцию, чтобы иметь версию, допускающую обнуление.», Если вы делаете хотите, чтобы ваш клиент мог узнать, есть ли у SomeNumber Значение тогда у вас есть несколько вариантов:

  • Выставить собственность как bool SomeNumberHasValue
  • Измените тип SomeNumber на int?
  • Добавить второе свойство SomeNumberNullable с типом возврата int?

Однако одно свойство не может иногда возвращать int и возвращать int? в другое время.

Другой вариант - использовать метод для доступа к значению, например так:

public int? GetSomeNumber(bool canReturnNull)
{
    if (canReturnNull)
        return _someNumber;

    return _someNumber.HasValue ? _someNumber.Value : 0;
}

По сути, вы проделываете большую работу, чтобы ваши клиенты могли легко обрабатывать нулевую проверку, не скрывая тот факт, что значение может быть нулевым. В чем выгода?

...