NetFabric/NetFabric.Hyperlinq

There is no need for IValueEnumerator

aalmada opened this issue · 1 comments

The following is from a comment on Medium by @qwertie:

There is no need for IValueEnumerator — it is the same as IEnumerator except that it is IDisposable. Does it really need to be disposable?

The important part is IValueEnumerable. But I would call it simply IEnumerable and define it like this:

public interface IEnumerable<T, TEnumerator>
 where TEnumerator : IEnumerator<T>, IDisposable {
   TEnumerator GetEnumerator();
}

But you will have a problem in case someone implements a class X that implements both IEnumerable<T> and IEnumerable<T, TEnumerator>. The compiler will say that an extension method like x.Select(e=>e) is ambiguous between System.Linq.Enumerable.Select and NetFabric.Hyperlinq.Enumerable.Select. To avoid this problem, it needs to be derived from IEnumerable<T>:

public interface IEnumerable<T, TEnumerator> : IEnumerable<T>
  where TEnumerator : IEnumerator<T>, IDisposable {
    TEnumerator GetEnumerator();
}

@qwertie I finally refactored the interfaces to the following:

using System.Collections.Generic;

namespace NetFabric.Hyperlinq
{
    public interface IValueEnumerable<out T, TEnumerator>
        : IEnumerable<T>
        where TEnumerator : struct, IEnumerator<T>
    {
        new TEnumerator GetEnumerator();
    }

    public interface IValueReadOnlyCollection<out T, TEnumerator>
        : IReadOnlyCollection<T>
        , IValueEnumerable<T, TEnumerator>
        where TEnumerator : struct, IEnumerator<T>
    {
    }

    public interface IValueReadOnlyList<out T, TEnumerator>
        : IReadOnlyList<T>
        , IValueReadOnlyCollection<T, TEnumerator>
        where TEnumerator : struct, IEnumerator<T>
    {
    }
}

Check it in the vNext branch.