Click here to Skip to main content
15,907,395 members
Home / Discussions / C#
   

C#

 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? Pin
Taka Muraoka28-Jan-08 18:40
Taka Muraoka28-Jan-08 18:40 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? Pin
Scott Dorman29-Jan-08 4:33
professionalScott Dorman29-Jan-08 4:33 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? Pin
Taka Muraoka29-Jan-08 4:47
Taka Muraoka29-Jan-08 4:47 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? Pin
Scott Dorman29-Jan-08 5:43
professionalScott Dorman29-Jan-08 5:43 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? Pin
Taka Muraoka29-Jan-08 15:46
Taka Muraoka29-Jan-08 15:46 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? Pin
Scott Dorman30-Jan-08 3:02
professionalScott Dorman30-Jan-08 3:02 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? [modified] Pin
Taka Muraoka30-Jan-08 4:23
Taka Muraoka30-Jan-08 4:23 
GeneralRe: What's the point of IEnumerable and IEnumerable<T>? Pin
Scott Dorman30-Jan-08 14:56
professionalScott Dorman30-Jan-08 14:56 
Taka Muraoka wrote:
That's right, this is the behaviour I want but I was playing with the code you gave because I wanted to get a better handle on what was really going on. I was wondering if the non-generic GetEnumerator() would get called if I tried to iterate using something other than int's.


That's probably the best way to understand it. Hopefully it is clearer for you know.

Taka Muraoka wrote:
If I write a C++ class that derives from an interface that in turn derives from another interface, my class has to effectively implement two interfaces. This is reinforced by the fact that I have to implement both versions of GetEnumerator().


This is the same in C#. Your class X derives from the IEnumerable<T> interface, which derives from IEnumerable, so you end up having to implement both interfaces. Since each interface defines a method named GetEnumerator you must specifically tell the compiler which method is being implemented.

Interface declarations in C# do not allow you to specify an access modifier. If it's declared in an interface it's a public method or property. In order to declare the same-named method from two different interfaces you must "inform" the compiler how to tell them apart.

Ordinarily when you implement an interface, you simply define the body for the matching method signature:
C#
public IEnumerator GetEnumerator() { ... }
Since (for this part of the example) there is only one method named GetEnumerator the compiler is able to determine which method implements the interface. However, when you add the IEnumerator<T> interface you now have an ambiguous match. In order to resolve that ambiguity, one (or both) of the methods must be defined "in terms of their interface". This is what is meant by an explicit implementation. You are explicitly declaring that you are implementing the IEnumerable.GetEnumerator method.

The key thing here is that when you explicitly implement an interface member you cannot specify an access modifier. It's an implied accessibility, which is something I call "psuedo-public". That is, it's a public member but is not visible unless the object is explicitly cast to that interface.

So, in my example
C#
class X : IEnumerable<int>
{
    private List<int> mList = new List<int>();
    public X()
    {
        mList.Add(1); mList.Add(2); mList.Add(3);
    }
 
    public IEnumerator<int> GetEnumerator()
    {
        return mList.GetEnumerator();
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return mList.GetEnumerator();
    }
}
I am explicitly implementing the IEnumerable.GetEnumerator member. In the calling code, it will default to using the implicit implementation (the public IEnumerator<int> GetEnumerator()) because the call isn't being cast to IEnumerable.

Defining the member in an interface doesn't imply that it is virtual at all. It does imply, however, that you must implement that member. This is different than a pure virtual method in C++ since virtual members must be defined in a class, and abstract members (which is the C# equivalent to pure virtual) must be defined in an abstract class.

Taka Muraoka wrote:
The fact that your 2b code works really makes me think foreach is ignoring the interface hierarchy and just looks for a public GetEnumerator() method. But on the other hand, the generic GetEnumerator() definition in 2b must be equivalent to the one in 2a (i.e. 2 different ways of defining the same thing, otherwise the compiler would be complaining about an un-implemented interface method) but so then, why does declaring it public make a difference?!


Hopefuly my answers above make this clearer.

Taka Muraoka wrote:
why does declaring it public make a difference?!


Again, hopefuly my answers above make it clearer as to why declaring one of the methods public makes a difference.

Taka Muraoka wrote:
I thought you couldn't change the access privilege when implementing interface methods? So both X's GetEnumerator's are already public, because that's how they're defined in their respective interfaces.


You are correct. You can't change the access level when implementing an interface. Remember, everything in an interface is always considered public. However, you can "hide" the implementation so it is only visible when the caller is cast to a specific interface by declaring the implementations explicitly. When you do that, you aren't allowed to specify an access modifier since one is essentially implied.

Taka Muraoka wrote:
Having this compile...but not this...just seems bizarre to me Unless the former is a brand new definition of GetEnumerator() that has nothing to do with either of the two interfaces (hence my suspicion foreach is ignoring them).


Again, this is the difference between the implicit and explicit implementations. It isn't a new definition, simply an explicit definition of one of the interface members.

Taka Muraoka wrote:
Aaargh, now I'm really confused


Sorry...hopefuly this response hasn't confused you more.

Scott.

—In just two days, tomorrow will be yesterday.
—Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai

[Forum Guidelines] [Articles] [Blog]

GeneralRe: What's the point of IEnumerable and IEnumerable&lt;T&gt;? Pin
Taka Muraoka30-Jan-08 21:46
Taka Muraoka30-Jan-08 21:46 
Generalclass Pin
keisal25-Jan-08 13:57
keisal25-Jan-08 13:57 
GeneralRe: class Pin
Luc Pattyn25-Jan-08 15:51
sitebuilderLuc Pattyn25-Jan-08 15:51 
GeneralRe: class Pin
Paul Conrad25-Jan-08 15:52
professionalPaul Conrad25-Jan-08 15:52 
GeneralRe: class Pin
BoneSoft25-Jan-08 18:55
BoneSoft25-Jan-08 18:55 
GeneralRe: class Pin
DaveyM6925-Jan-08 21:29
professionalDaveyM6925-Jan-08 21:29 
GeneralRe: class Pin
Spacix One26-Jan-08 5:57
Spacix One26-Jan-08 5:57 
AnswerRe: class Pin
Guffa26-Jan-08 8:16
Guffa26-Jan-08 8:16 
GeneralGeneric List Remove method delay Pin
DaveyM6925-Jan-08 12:35
professionalDaveyM6925-Jan-08 12:35 
GeneralRe: Generic List Remove method delay Pin
Abhijit Jana25-Jan-08 23:27
professionalAbhijit Jana25-Jan-08 23:27 
GeneralRe: Generic List Remove method delay Pin
DaveyM6925-Jan-08 23:31
professionalDaveyM6925-Jan-08 23:31 
GeneralString Reversal plus character replacement Pin
BREdwards25-Jan-08 11:25
BREdwards25-Jan-08 11:25 
GeneralRe: String Reversal plus character replacement Pin
pmarfleet25-Jan-08 11:54
pmarfleet25-Jan-08 11:54 
GeneralRe: String Reversal plus character replacement Pin
BREdwards25-Jan-08 12:16
BREdwards25-Jan-08 12:16 
GeneralRe: String Reversal plus character replacement Pin
pmarfleet25-Jan-08 12:25
pmarfleet25-Jan-08 12:25 
GeneralRe: String Reversal plus character replacement Pin
PIEBALDconsult25-Jan-08 13:21
mvePIEBALDconsult25-Jan-08 13:21 
GeneralRe: String Reversal plus character replacement Pin
BREdwards25-Jan-08 17:31
BREdwards25-Jan-08 17:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.