> it using this type of construction.
> IEnumerator IEnumerable.GetEnumerator()
> {
> return new TreeEnumerator<T>(this);>
> }
> ...method GetEnumerator was not shown in the Intelligens...
> ...Why ?
Because you have used explicit implementation. If you had used
implicit implementation it would show:
public IEnumerator GetEnumerator()
If you are implementing IEnumerable<T>, it is common to use explicit
implementation for the untyped IEnumerable version, and implicit
implementation for the typed IEnumerable<T> version [of
GetEnumerator()], with the IEnumerable version simply return the
public GetEnumerator():
public IEnumerator<T> GetEnumerator() {...whatever...}
IEnumerator IEnumerable.GetEnumerator() {return GetEnumerator();}
However, "foreach" should be able to use either implicit or explicit
construction without any issues.
I think that addresses most of Q1 and Q2 (it was long, so maybe I
missed something); perhaps post anything I've missed?
For info, in C# 2 it is uncommon to write your own IEnumerator[<T>]
implementation; you can get the compiler to do it for you very
effectively (and less error-prone). For instance:
public IEnumerator<int> GetEnumerator() {
for(int i = 0; i < 100; i++) {
yield return i;
}
}
Actually creates a hidden type that does everything necessary as a
state machine to return 0-99 as a foreach result. Or to illustrate
from unioning 2 lists:
public IEnumerator<T> GetEnumerator() {
foreach(T t in firstList) {
yield return t;
}
foreeach(T t in secondList) {
yield return t;
}
}
You might find you can write your enumerator a lot easier using "yield
return" and "yield break".
Put it this way: I haven't written a single IEnumerator[<T>]
implementation sinc moving to .NET 2.0, but I've written lots of
"yield return"...
Marc
Marc Gravell - 01 Mar 2008 10:42 GMT
Additional; Jon Skeet's new book (C# In Depth) has a really good
explanation of "yield return" etc; the entire of chapter 6, in fact -
covering all the subtleties, nuances, etc. Not yet in print, but you
can get the "early access" version as PDF.
I see I missed a question:
>which one do you recommend ?. I thing
>that using this one is better
>public IEnumerator GetEnumerator()
>{
> return new TreeEnumerator<T>(this);
>}
You can't do that if you are using implicit implementation for the
typed version, as you can't (in C#) have overloads that differ only by
the return type - i.e.
IEnumerator GetEnumerator() {...}
and
IEnumerator<T> GetEnumerator() {...}
would clash.
And given that the second is the preferred option, it is this that is
normally exposed on the public API, using explicit implementation for
the untyped version.
Marc
Tony Johansson - 01 Mar 2008 11:10 GMT
Hello!
In your posting you talk about typed version and untyped version can you
please explain exactly what you mean by that ?
//Tony
> Additional; Jon Skeet's new book (C# In Depth) has a really good
> explanation of "yield return" etc; the entire of chapter 6, in fact -
[quoted text clipped - 22 lines]
>
> Marc
Marc Gravell - 01 Mar 2008 11:31 GMT
> In your posting you talk about typed version and untyped version can you
> pease explain exactly what you mean by that ?
.NET 1.x had the IEnumerable/IEnumerator interfaces, but not
"generics", and so IEnumator is defined as having:
object Current { get; }
There are three problems here:
* the caller has to keep casting the Current value to whatever they
expect it to be
* the compiler can't verify much for you
* it needs to "box" value-types (int, float, etc) [simply to be
unboxed when you cast it back]
.NET 2.0 introduced generics, and provided the IEnumerable<T>/
IEnumerator<T> interfaces. The main change is that IEnumerator<T> has:
T Current { get; }
i.e. if you implement IEnumerable<Foo>, the compiler knows that each
value (from the enumerator) is a Foo:
* no need to cast
* the compiler can verify that you aren't doing anything clearly wrong
* there is no need to box/unbox value-types
The decision was taken that IEnumerable<T> : IEnumerable, which means
that if you implement IEnumerable<T>, then any code that only knows
about IEnumerable can still use your enumerator perfectly happily, but
using the older "object" approach. But because the GetEnumerable()
method now exists twice, you need to make it clear to the compiler
which is which, by using explicit implementation of
IEnumerable.GetEnumerator() [the IEnumerable<T>.GetEnumerable()
version being preferred on the public interface for all the reasons I
have already listed].
Marc
Marc Gravell - 01 Mar 2008 11:34 GMT
[typo: GetEnumerable() => GetEnumerator()]
Tony Johansson - 01 Mar 2008 11:41 GMT
Hello!
Below I have two different versions(both use explicit) the first one is the
typed version and the second one is untyped version. I think.
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{ return new TreeEnumerator<T>(this); }
IEnumerator IEnumerable.GetEnumerator() explicit
{ throw new Exception("The method or operation is not implemented."); }
So you mean in this case the most common is to change the typed version
using implicit decalaration like the below.
public IEnumerator<T> GetEnumerator()
{ return new TreeEnumerator<T>(this); }
Have I understood you correctly ?
//Tony
> Hello!
>
[quoted text clipped - 29 lines]
>>
>> Marc
Marc Gravell - 01 Mar 2008 23:24 GMT
> So you mean in this case the most common is to change the typed version
> using implicit decalaration like the below
That is exactly what I mean. Of course, if you are only using
"foreach" etc, it probably won't matter much either way - but that is
the common approach.
Marc
On Mar 1, 11:08 am, "Tony Johansson" <johansson.anders...@telia.com>
wrote:
> Hello!
>
[quoted text clipped - 86 lines]
>
> //Tony
Hello!
Since you implement the IEnumerable<> interface, which in turn
implements the non-generic IEnumerable interface, you want to use the
generic version's GetEnumerator method.
Try this:
// Generic implementation
public IEnumerator<T> GetEnumerator()
{
foreach (T node in theTree)
yield return T;
}
Since the generic version implements the non-generic, you want the non-
generic GetEnumerator method to call your generic one.
// Hide the non-generic implementation and return the generic
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
You will then be able to enumerate over the collection by either doing
a foreach or by getting the enumerator manually.