Lecture thumbnail 0:00 / 0:00 To be fair, what we’ve done in the binary tree was very flexible.
We had a method which returned inorder traversal or a property rather, but it had a method inside it.
So let’s suppose that you only have one way of iterating the tree.
Let’s suppose inorder traversal is the only way that you want to traverse a tree.
In this case, what you really want to write is something like the following var tree equals new binary
tree of int taking the root obviously.
And then you want to say something like for each var node in tree and you want to write line the node
value node dot value for example, but you cannot do it.
And the reason you cannot do it is shown here.
So the binary tree is not enumerable.
Now what do you think it means for a type to be enumerable?
Do you think that an enumerable type is something which implements enumerable of T?
Well, no.
In actual fact you don’t need enumerable of t.
All you need is a method called get enumerator.
And this method has to return an iterator type just like the inorder iterator that we’ve built.
And this iterator type has to have two things.
It has to have a method called movenext which returns a boolean, which we already have, and it also
has to have a property called current which points to the current element.
So here we have a field, let’s change it into an automatic property and we are done.
We are able to use this iterator as a fully fledged iterator which can be used in a for each statement.
So going back to the binary tree, what we can do is we can yield this inorder iterator, we can return
this inorder iterator of int whenever somebody calls get enumerator.
So somebody calls, get enumerator and we return new in order iterator specifying the root node.
Okay, so let’s see what’s going on here.
Can we are we allowed to take this argument here?
Oh, hold on.
Let’s go and take a look at the constructor of the inorder iterator.
Let’s see what’s going on here.
Now it is taking a node of t, so maybe we didn’t save the node of t.
I don’t know.
Let’s take a look at root for example.
What’s going on here?
What is it saying?
It’s saying argument type is not assignable to parameter type node of int.
So node of t is not assignable to node of.
And oh yeah, that has to be a T because it can be virtually any type.
Okay.
So now this has to be node of iterator of T as well and we are done.
Now amazingly enough, this should now work.
Let’s take a look at the error here.
So it’s still saying, oh, this thing is not enumerable, but in actual fact it is.
In actual fact it is.
Let me add a public keyword here.
Notice the highlighting is gone.
It’s now apparently valid.
So let me just recap what’s going on here.
Tree.
The binary tree is not an enumerable.
It does not say oh I an I enumerable of node of t.
It doesn’t say anything like that.
And still, in spite of this, it works perfectly fine in a for each loop.
And if we actually execute this just to prove to you that it works, here is the output 213.
So obviously something clicked here.
And the reason why this works is because of duck typing, because what really happens is for each doesn’t
care whether your type is enumerable of T, all it does is it goes off looking for a method called getenumerator.
If it finds this method, then it looks at the return type of this method and it asks the following
question Do you have a property called current?
Do you have a boolean returning method called Movenext?
If you do, then everything is fine and we’re going to execute this.
So provided you only need one iterator, you can actually build and expose this separate object using
Getenumerator without even having to do your own enumerable of T and implementing those methods.
You can just have this duck typing approach.
Now, I wouldn’t say it’s the most transparent and easy to understand mechanism, but it is available
if you need it for some reason.
Play Play Play Stop Play Start Play information alert