C# - How to create an array from an enumerator
Asked Answered
M

3

15

In C#, what's the most elegant way to create an array of objects, from an enumerator of objects? e.g. in this case I have an enumerator that can return byte's, so I want to convert this to byte[].

EDIT: Code that creates the enumerator:

IEnumerator<byte> enumerator = anObject.GetEnumerator();
Migration answered 21/8, 2010 at 12:39 Comment(5)
IEnumerator or IEnumerable? IEnumerator<T> or IEnumerable<T>?Freehanded
its - IEnumerator<byte> enumurator = updDnsPacket.GetEnumerator();Migration
Looks like you accepted the wrong answer.Plowshare
@DaveHillier: If you have an IEnumerable<T>, it makes little sense to get the IEnumerator<T> and then ask how to create an array from that -- you can easily create the array from the IEnumerable<T>. You are, of course, right if all you have is an IEnumerator<T>. Then the answer is a bit different from mine. But I've never met the case so far where you have the IEnumerator<T> and not the IEnumerable<T>.Freehanded
@Freehanded - I have and I came across this question. This question wasted my time as it is incorrect. It is in a crappy port of a Java library.Plowshare
F
2

Assuming you have an IEnumerable<T>, you can use the Enumerable.ToArray extension method:

IEnumerable<byte> udpDnsPacket = /*...*/;

byte[] result = udpDnsPacket.ToArray();
Freehanded answered 21/8, 2010 at 12:41 Comment(8)
I don't see a "ToArray()" in the intellisense? Is this one of these cases I have to add a using statement to get some extra methods?Migration
@Greg: Yes. You need to add using System.Linq; in order to make the Enumerable class visible.Freehanded
got it thanks - it doesn't add any real overhead behind the scenes re pulling in the Linq libraries?Migration
Nope, if you are already using 3.5 or greater, then you already have the Linq extensions so, there is no overhead in "pulling" them in.Sentient
Is it just me or is the question clearly NOT about an IEnumerable but about an IEnumerator?Antifriction
@Ronald Wildenberg: It is somewhat unusual to have an IEnumerator and not an IEnumerable. The original question was not that clear about this as it is now. Also, the OP's updDnsPacket object looks quite likely to implement IEnumerable, so why not take advantage of that instead of following the false assumption that the only way to create an array from an IEnumerable is to get the enumerator and continue from there.Freehanded
@dtb: The comment wasn't really addressed at you but more at everyone who voted you up :) Reading the inital question I understand the assumption.Antifriction
The negativism in the comments here and in the OP amazes me. This is a classic example of an "XY" problem - the author needed to do "X", but thought that the way to do it was "Y" and asked about "Y" instead. dtp very wisely noticed this and gave the author the information for "X" instead. This was the best possible answer for the author's need and fully justifies them accepting it. It may not be what you need (or it may - are you chasing an "XY" problem yourself?) , but it is not your call to declare the author wrong for accepting it.Arnoldoarnon
S
32

OK, So, assuming that you have an actual enumerator (IEnumerator<byte>), you can use a while loop:

var list = new List<byte>();
while(enumerator.MoveNext())
  list.Add(enumerator.Current);
var array = list.ToArray();

In reality, I'd prefer to turn the IEnumerator<T> to an IEnumerable<T>:

public static class EnumeratorExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this IEnumerator<T> enumerator)
    {
      while(enumerator.MoveNext())
          yield return enumerator.Current;
    }
}

Then, you can get the array:

var array = enumerator.ToEnumerable().ToArray();

Of course, all this assumes you are using .Net 3.5 or greater.

Sentient answered 21/8, 2010 at 12:53 Comment(6)
The foreach construct actually doesn't care if you're an IEnumerable as long as you have GetEnumerator declared. I only mention this because you don't. =)Stile
@Marc: I don't see how that is relevant to my answer? I am not using foreach here.Sentient
@Brian, as a (imo) cleaner alternative to whileStile
@Marc: But you can't do foreach on an IEnumerator. You can only do it on an IEnumerable. My while loop translates an IEnumerator to an IEnumerable.Sentient
@Brian Genisio: Which brings me back to my original comment. The poster says he has a class that has a method named GetEnumerator that returns an IEnumerator. This is enough for foreach to do it's work. foreach(var b in updDnsPacket) list.Add(b); That's all I was getting at, sorry for being so vague.Stile
@marc Ok, I get what you are saying now. I wrote my answer before he showed the example code, so I missed it. I still prefer ToEnumerable().ToArray() approach for his situation though.Sentient
A
4

Since you have an IEnumerator<byte> and not an IEnumerable<byte>, you cannot use Linq's ToArray method. ToArray is an extension method on IEnumerable<T>, not on IEnumerator<T>.

I'd suggest writing an extension method similar to Enumerable.ToArray but then for the purpose of creating an array of your enumerator:

public T[] ToArray<T>(this IEnumerator<T> source)
{
    T[] array = null;
    int length = 0;
    T t;
    while (source.MoveNext())
    {
        t = source.Current();
        if (array == null)
        {
            array = new T[4];
        }
        else if (array.Length == length)
        {
            T[] destinationArray = new T[length * 2];
            Array.Copy(array, 0, destinationArray, 0, length);
            array = destinationArray;
        }
        array[length] = t;
        length++;
    }
    if (array.Length == length)
    {
        return array;
    }
    T[] destinationArray = new T[length];
    Array.Copy(array, 0, destinationArray, 0, length);
    return destinationArray;
}

What happens is that you iterate your enumerator item by item and add them to an array that is gradually increasing in size.

Antifriction answered 21/8, 2010 at 12:54 Comment(2)
got to run - will test the Linq solution when I'm back to see if it works (the method appears) - why do you say I cannot use the Linq ToArray method?Migration
He means you can call ToArray() on IEnumerable (so on udpDnsPacket in your case), but not on IEnumeratorEmbryectomy
F
2

Assuming you have an IEnumerable<T>, you can use the Enumerable.ToArray extension method:

IEnumerable<byte> udpDnsPacket = /*...*/;

byte[] result = udpDnsPacket.ToArray();
Freehanded answered 21/8, 2010 at 12:41 Comment(8)
I don't see a "ToArray()" in the intellisense? Is this one of these cases I have to add a using statement to get some extra methods?Migration
@Greg: Yes. You need to add using System.Linq; in order to make the Enumerable class visible.Freehanded
got it thanks - it doesn't add any real overhead behind the scenes re pulling in the Linq libraries?Migration
Nope, if you are already using 3.5 or greater, then you already have the Linq extensions so, there is no overhead in "pulling" them in.Sentient
Is it just me or is the question clearly NOT about an IEnumerable but about an IEnumerator?Antifriction
@Ronald Wildenberg: It is somewhat unusual to have an IEnumerator and not an IEnumerable. The original question was not that clear about this as it is now. Also, the OP's updDnsPacket object looks quite likely to implement IEnumerable, so why not take advantage of that instead of following the false assumption that the only way to create an array from an IEnumerable is to get the enumerator and continue from there.Freehanded
@dtb: The comment wasn't really addressed at you but more at everyone who voted you up :) Reading the inital question I understand the assumption.Antifriction
The negativism in the comments here and in the OP amazes me. This is a classic example of an "XY" problem - the author needed to do "X", but thought that the way to do it was "Y" and asked about "Y" instead. dtp very wisely noticed this and gave the author the information for "X" instead. This was the best possible answer for the author's need and fully justifies them accepting it. It may not be what you need (or it may - are you chasing an "XY" problem yourself?) , but it is not your call to declare the author wrong for accepting it.Arnoldoarnon

© 2022 - 2024 — McMap. All rights reserved.