C# Class is IEnumerable AND an IEnumerator at the same time. What are the issues with this?

后端 未结 2 1839

I have a class called GenericPermutations that is both enumerable and an enumerator. Its job is to take an ordered list of objects and iterate through each permutation of t

2条回答
  •  温柔的废话
    2021-01-05 08:13

    Reduce your confusion (?) by using the generic versions of IEnumerable and IEnumerator.

    A permutation enumerable is IEnumerable>. So you might have something like

    IEnumerable> GetPermutations(IEnumerable sequence)
    {
        return new Permuter(sequence);
    }
    

    and

    public class Permuter : IEnumerable> { ... }
    

    Furthermore, I've seen more than one case where a single type implemented both IEnumerable and IEnumerator; its GetEnumerator method was simply return this;.

    I think such a type would need to be a struct, though, because if it were a class you'd have all sorts of problems if you called GetEnumerator() a second time before the first enumeration was completed.

    EDIT: Consuming the permuter

    var permuter = GetPermutations(sequence);
    foreach (var permutation in permuter)
    {
        foreach (var item in permutation)
            Console.Write(item + "; ");
        Console.WriteLine();
    }
    

    Assuming the input sequence is { 1, 2, 3 }, the output is

    1; 2; 3; 
    1; 3; 2; 
    2; 1; 3; 
    2; 3; 1; 
    3; 1; 2; 
    3; 2; 1; 
    

    EDIT:

    Here's a super-inefficient implementation to illustrate the suggestion:

    public class Permuter : IEnumerable>
    {
        private readonly IEnumerable _sequence;
    
        public Permuter(IEnumerable sequence)
        {
            _sequence = sequence;
        }
    
        public IEnumerator> GetEnumerator()
        {
            foreach(var item in _sequence)
            {
                var remaining = _sequence.Except(Enumerable.Repeat(item, 1));
                foreach (var permutation in new Permuter(remaining))
                    yield return Enumerable.Repeat(item, 1).Concat(permutation);
            }
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    

提交回复
热议问题