Skip to main content
added 23 characters in body
Source Link
user73941
user73941
  internal class AddEnumerable<T> : IAddEnumerable<T>
  {
    private IEnumerable<T> _sequence;
    private readonly T _elementToAdd;
    private Func<IEnumerable<T>, T, bool> _expression;

    private bool _added;

    public AddEnumerable(IEnumerable<T> sequence, T elementToAdd)
    {
      _sequence = sequence;
      _elementToAdd = elementToAdd;
    }

    public IEnumerable<T> If(Func<IEnumerable<T>, T, bool> expression)
    {
      _expression = expression;
      return this;
    }

    public IEnumerator<T> GetEnumerator()
    {
      if (_added)
        return _sequence.GetEnumerator();

      if (_expression !=== null &&|| _expression(_sequence, _elementToAdd))
      {
        _sequence = _sequence.AddItem(_elementToAdd);
      }
      _added = true;

      return _sequence.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
  }
  internal class AddEnumerable<T> : IAddEnumerable<T>
  {
    private IEnumerable<T> _sequence;
    private readonly T _elementToAdd;
    private Func<IEnumerable<T>, T, bool> _expression;

    private bool _added;

    public AddEnumerable(IEnumerable<T> sequence, T elementToAdd)
    {
      _sequence = sequence;
      _elementToAdd = elementToAdd;
    }

    public IEnumerable<T> If(Func<IEnumerable<T>, T, bool> expression)
    {
      _expression = expression;
      return this;
    }

    public IEnumerator<T> GetEnumerator()
    {
      if (_added)
        return _sequence.GetEnumerator();

      if (_expression != null && _expression(_sequence, _elementToAdd))
      {
        _sequence = _sequence.AddItem(_elementToAdd);
      }
      _added = true;

      return _sequence.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
  }
  internal class AddEnumerable<T> : IAddEnumerable<T>
  {
    private IEnumerable<T> _sequence;
    private readonly T _elementToAdd;
    private Func<IEnumerable<T>, T, bool> _expression;

    private bool _added;

    public AddEnumerable(IEnumerable<T> sequence, T elementToAdd)
    {
      _sequence = sequence;
      _elementToAdd = elementToAdd;
    }

    public IEnumerable<T> If(Func<IEnumerable<T>, T, bool> expression)
    {
      _expression = expression;
      return this;
    }

    public IEnumerator<T> GetEnumerator()
    {
      if (_added)
        return _sequence.GetEnumerator();

      if (_expression == null || _expression(_sequence, _elementToAdd))
      {
        _sequence = _sequence.AddItem(_elementToAdd);
      }
      _added = true;

      return _sequence.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
  }
added 1311 characters in body
Source Link
user73941
user73941

An idea came to my mind: Because you return this from If(), I think, you can avoid the repetitive code in there by saving the predicate and then handle everything in GetEnumerator():

  internal class AddEnumerable<T> : IAddEnumerable<T>
  {
    private IEnumerable<T> _sequence;
    private readonly T _elementToAdd;
    private Func<IEnumerable<T>, T, bool> _expression;

    private bool _added;

    public AddEnumerable(IEnumerable<T> sequence, T elementToAdd)
    {
      _sequence = sequence;
      _elementToAdd = elementToAdd;
    }

    public IEnumerable<T> If(Func<IEnumerable<T>, T, bool> expression)
    {
      _expression = expression;
      return this;
    }

    public IEnumerator<T> GetEnumerator()
    {
      if (_added)
        return _sequence.GetEnumerator();

      if (_expression != null && _expression(_sequence, _elementToAdd))
      {
        _sequence = _sequence.AddItem(_elementToAdd);
      }
      _added = true;

      return _sequence.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
  }

An idea came to my mind: Because you return this from If(), I think, you can avoid the repetitive code in there by saving the predicate and then handle everything in GetEnumerator():

  internal class AddEnumerable<T> : IAddEnumerable<T>
  {
    private IEnumerable<T> _sequence;
    private readonly T _elementToAdd;
    private Func<IEnumerable<T>, T, bool> _expression;

    private bool _added;

    public AddEnumerable(IEnumerable<T> sequence, T elementToAdd)
    {
      _sequence = sequence;
      _elementToAdd = elementToAdd;
    }

    public IEnumerable<T> If(Func<IEnumerable<T>, T, bool> expression)
    {
      _expression = expression;
      return this;
    }

    public IEnumerator<T> GetEnumerator()
    {
      if (_added)
        return _sequence.GetEnumerator();

      if (_expression != null && _expression(_sequence, _elementToAdd))
      {
        _sequence = _sequence.AddItem(_elementToAdd);
      }
      _added = true;

      return _sequence.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
  }
Source Link
user73941
user73941

I like the idea - but have the following comments:

  var originalList = Enumerable.Range(1, 12).ToList();
  IEnumerable<int> myList = originalList.Add(12).If((list, item) => !list.Contains(item));

If the originalList is defined explicit as something that implements ICollection, then you get a compiler error saying: "Operator '.' cannot be applied to operand of type 'void'", because Add() is already a method returning void.


    public IEnumerator<T> GetEnumerator()
    {
        if (_added) 
            return _sequence.GetEnumerator();

        _sequence = _sequence.AddItem(_elementToAdd);
        _added = true;

        return _sequence.GetEnumerator();
    }
            
    IEnumerator IEnumerable.GetEnumerator()
    {
        if (_added) 
            return _sequence.GetEnumerator();

        _sequence = _sequence.AddItem(_elementToAdd);
        _added = true;

        return _sequence.GetEnumerator();
    }

Don't repeat code - the second method can call the first:

IEnumerator IEnumerable.GetEnumerator()
{
  return GetEnumerator();
}

public interface IAddEnumerable<T> : IEnumerable<T>
{
    IEnumerable<T> If(Func<IEnumerable<T>, T, bool> expression);
}

By renaming this interface you could extend its usability to for instance a sequence like:

data.Remove(12).If(<predicate>);

Maybe IPredicate or something like that.


Although I know that @new, @this etc. are valid variable names, I personally always avoid them, because they distract the reading. I have never been in a situation where it was unavoidable to use them.


I understand, that you want a fluid approach, and therefore define the If method separately, but I think, I would concatenate the behavior to a single function like:

public static IEnumerable<T> AddIf<T>(this IEnumerable<T> source, T element, Func<IEnumerable<T>, T, bool> predicate)
{
  return predicate(source, element) ? source.AddItem(element) : source;
}