简体   繁体   中英

Adding Methods to Nullable Types

We have come across a scenario where we need to track the setting and unsettling of a nullable type.

so something like

int? value

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

we would also need a clear function

value.clear();

The concept is that the data has an extra state that is the set state.

so NULL(set) and NULL(unset) have different meanings. and then you have the value (set) for most cases and the value(unset) (this last case would have no meaning)

is there a way using extension methods or some other pattern that could solve this problem. my current thought is that we will have to revert to an extended class of some sort.

You can control the nullable type with extension methods - ie: add methods to work with it, etc.

However, at some point, when you start adding behavior to an object like this, the object itself really starts feeling more like it should be in a class of its own. Nullable<T> is nice since it's really still one value - just a value that can be null. It still doesn't have behavior in and of itself.

If you want to add custom behavior, filtering, events for tracking, etc., then I'd consider making your own custom type for this.

Here is an example.

    public static class NullableInt32Extensions
    {
        public static Boolean IsSet(this Nullable<Int32> value)
        {
            return value.HasValue;
        }       
    }

I'm trying to understand what you're after. I think it is something like the below (Dump is from LINQPad , just think Console.WriteLine). Overall, I don't think this is a good idea, because you provide something obscure that does not work as expected. Unless I mis-understand what you want.

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 ) );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM