This is in C#, I have a class that I am using from some else\'s DLL. It does not implement IEnumerable but has 2 methods that pass back a IEnumerator. Is there a way I can u
According to MSDN:
foreach (type identifier in expression) statement
where expression is:
Object collection or array expression. The type of the collection element must be convertible to the identifier type. Do not use an expression that evaluates to null. Evaluates to a type that implements IEnumerable or a type that declares a GetEnumerator method. In the latter case, GetEnumerator should either return a type that implements IEnumerator or declares all the methods defined in IEnumerator.
Given class X with methods A and B that both return IEnumerable, you could use a foreach on the class like this:
foreach (object y in X.A())
{
//...
}
// or
foreach (object y in X.B())
{
//...
}
Presumably the meaning for the enumerables returned by A and B are well-defined.
foreach
does not require IEnumerable
, contrary to popular belief. All it requires is a method GetEnumerator
that returns any object that has the method MoveNext
and the get-property Current
with the appropriate signatures.
/EDIT: In your case, however, you're out of luck. You can trivially wrap your object, however, to make it enumerable:
class EnumerableWrapper {
private readonly TheObjectType obj;
public EnumerableWrapper(TheObjectType obj) {
this.obj = obj;
}
public IEnumerator<YourType> GetEnumerator() {
return obj.TheMethodReturningTheIEnumerator();
}
}
// Called like this:
foreach (var xyz in new EnumerableWrapper(yourObj))
…;
/EDIT: The following method, proposed by several people, does not work if the method returns an IEnumerator
:
foreach (var yz in yourObj.MethodA())
…;
Re: If foreach doesn't require an explicit interface contract, does it find GetEnumerator using reflection?
(I can't comment since I don't have a high enough reputation.)
If you're implying runtime reflection then no. It does it all compiletime, another lesser known fact is that it also check to see if the returned object that might Implement IEnumerator is disposable.
To see this in action consider this (runnable) snippet.
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication3
{
class FakeIterator
{
int _count;
public FakeIterator(int count)
{
_count = count;
}
public string Current { get { return "Hello World!"; } }
public bool MoveNext()
{
if(_count-- > 0)
return true;
return false;
}
}
class FakeCollection
{
public FakeIterator GetEnumerator() { return new FakeIterator(3); }
}
class Program
{
static void Main(string[] args)
{
foreach (string value in new FakeCollection())
Console.WriteLine(value);
}
}
}
No, you don't and you don't even need an GetEnumerator method, e.g.:
class Counter
{
public IEnumerable<int> Count(int max)
{
int i = 0;
while (i <= max)
{
yield return i;
i++;
}
yield break;
}
}
which is called this way:
Counter cnt = new Counter();
foreach (var i in cnt.Count(6))
{
Console.WriteLine(i);
}