Добавление методов к обнуляемым типам - PullRequest
2 голосов
/ 21 августа 2009

Мы столкнулись со сценарием, в котором нам нужно отследить установку и отключение обнуляемого типа.

так что-то вроде

int? value

if(value.isSet())
{
  addTocollection();
}

нам также нужна ясная функция

value.clear();

Концепция заключается в том, что данные имеют дополнительное состояние, которое является заданным состоянием.

поэтому значения NULL (установлено) и NULL (не установлено) имеют разные значения. а затем у вас есть значение (установлено) для большинства случаев и значение (не установлено) (этот последний случай не будет иметь смысла)

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

Ответы [ 3 ]

2 голосов
/ 21 августа 2009

Вот пример.

    public static class NullableInt32Extensions
    {
        public static Boolean IsSet(this Nullable<Int32> value)
        {
            return value.HasValue;
        }       
    }
2 голосов
/ 21 августа 2009

Вы можете управлять обнуляемым типом с помощью методов расширения - то есть: добавлять методы для работы с ним и т. Д.

Однако, в какой-то момент, когда вы начинаете добавлять поведение к объекту, подобному этому, сам объектдействительно начинает чувствовать себя больше, как будто он должен быть в своем классе.Nullable<T> хорошо, так как это действительно одно значение - просто значение, которое может быть нулевым.Оно по-прежнему не имеет поведения само по себе.

Если вы хотите добавить пользовательское поведение, фильтрацию, отслеживание событий и т. Д., То я бы подумал о создании собственного пользовательского типа для этого.

1 голос
/ 21 августа 2009

Я пытаюсь понять, что вы ищете. Я думаю, что это что-то вроде ниже (дамп из LINQPad , просто подумайте Console.WriteLine). В целом, я не думаю, что это хорошая идея, потому что вы предоставляете что-то неясное, что не работает, как ожидалось. Если я не понимаю, что вы хотите.

void Main()
{
    int? x = null;
    var wrap = new NullableWrapper<int>( x );

    wrap.HasBeenSet.Dump();  // false
    wrap.HasValue.Dump();   // false

    wrap = 10;

    wrap.HasBeenSet.Dump();  // true
    wrap.HasValue.Dump();    // true
    wrap.Value.Dump();       // 10

    int? y = wrap;

    y.HasValue.Dump();   // True
    y.Value.Dump();      // 10

    wrap = null;
    wrap.HasBeenSet.Dump();  // Does now work like expected => bad
}

public class NullableWrapper<T> where T : struct
{
  private Nullable<T> _impl;
  private bool _hasBeenSet = false;

  public NullableWrapper( Nullable<T> t )
  {
    _impl = t;
    _hasBeenSet = t.HasValue;
  }

  public bool HasBeenSet
  {
    get { return _hasBeenSet; }
  }

  public bool HasValue
  {
    get { return _impl.HasValue; }
  }

  public T Value
  {
    get { return _impl.Value; }
    set { _impl = value; _hasBeenSet = true; }
  }

  public void Clear()
  {
    _hasBeenSet = false;
  }

  public static implicit operator Nullable<T>( NullableWrapper<T> lhs )
  {
    return lhs._impl;
  }

  public static implicit operator NullableWrapper<T>( T rhs )
  {
    return( new NullableWrapper<T>( rhs ) );
  }
}
...