access modifiers for IEnumerable<T> and IEnumerable - c#

I'm a beginner in C#, just a question on IEnumerable and IEnumerable. I saw some code like this:
public class ShoppingCart : IEnumerable<Product>
{
public IEnumerator<Product> GetEnumerator()
{
return Products.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() //why 'public' is not needed?
{
return GetEnumerator();
}
}
I understand that first method is to implement the IEnumerator<Product> and second method is to implement IEnumerator since IEnumerator inherits from IEnumerator<Product>, but I don't understand why no 'public' access modifier is required for the second method? the first method does have 'public'.
And since both interfaces have same method signature, so we can see that second method use interfacename.methodname as explicit interface implementation, but why first method doesn't need this? shouldn't it be:
public IEnumerator<Product>.GetEnumerator()
{
...
}

It all comes down to the differences between implicit and explicit implementation of interface members.
An explicitly implemented member doesn't appear on the object unless the object is cast to the implemented interface. If you want someone to be able to call new ShoppingCart().GetEnumerator(), you must have a GetEnumerator method that's not an explicit implementation. Supposing it abides by the contract of one of the implemented interfaces, it'll implicitly implement the method on that interface. In this case, you must specify an access modifier because the main point of declaring the member is to make it available from this specific class. The modifier must be at least as permissive as the interface it's implementing (and it may be more permissive).
When explicitly implementing an interface member, you don't need to (and in fact, you cannot) specify the visibility (e.g. public) because the visibility is already set by the interface itself. Since the object must be cast to that interface in order to access that member, the member isn't considered to have any visibility beyond the visibility of the interface.
The first method in your code could have been explicitly implemented, like this:
IEnumerator<Product> IEnumerable<Product>.GetEnumerator()
{
return Products.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<Product>)this).GetEnumerator();
}
But whoever created that class chose to implement it implicitly so it would be available without having to first cast ShoppingList to an IEnumerable<Product>. Notice how this made the other method's implementation easier, because they could simply call this.GetEnumerator() without having to cast this first.
But since the second method only differs from the first by return type, it's impossible to implement both methods implicitly. It's common practice to implement the non-generic IEnumerable interface explicitly in these cases.

Related

Why can't I explicitly set the access level for GetEnumerator? [duplicate]

This question already has answers here:
Compilation Error: "The modifier 'public' is not valid for this item" while explicitly implementing the interface
(5 answers)
Closed 1 year ago.
I'm creating a simple collection that is implementing ICollection<T>, which from my understanding inherits from IEnumerable<T> (it is called interface inheritance at that point, correct?). With the implementation's auto generated code, there's a method for GetEnumerator using a syntax that has me a bit puzzled:
IEnumerator IEnumerable.GetEnumerator() { ... }
I initially thought this was a private method as all other auto generated blocks had specified public and I was trying to categorize and cleanup the implementation code. With that, out of habit, I try to always be explicit with my access modifiers and tried to mark the method with all access levels. However, this caused an error, very simple in nature:
The modifier x is not valid for this item.
This led me to question what's actually going on, yet my web searches aren't turning anything up.
Why can't I set the access level for this method explicitly?
Normally when you implement an interface, you must specify public for the methods and properties. In this case, not only do those methods and properties contribute towards implementing the interface, they are also just like any other regular method or property. Being able to add public to them makes sense. However, the IEnumerator.GetEnumerator you've declared here is a bit special.
This is an explicit interface implementation of IEnumerable.GetEnumerator. Just in case you didn't know, this is the non-generic (by which I mean, returns a non-generic IEnumerator) version of IEnumerable<T>.GetEnumerator, declared in IEnumerable (not to be confused with IEnumerable<T>!). Since IEnumerable<T> inherits from IEnumerable, you are required to implement both when implementing IEnumerable<T>.
If you didn't use an explicit interface implementation here, you would have two methods with the same name, both accepting no parameters, with only the return value different:
public IEnumerator<int> GetEnumerator()
{
...
}
public IEnumerator GetEnumerator() // CS0111
{
...
}
This is not allowed. This is where explicit interface implementation comes in. If you declare the non-generic GetEnumerator by prefixing the name of the interface where it comes from:
IEnumerator IEnumerable.GetEnumerator()
{
...
}
Then this method is only accessible on an expression with a type of IEnumerable. For example, let's say your collection is called MyCollection.
MyCollection myCollection = ...;
// this accesses the *generic* GetEnumerator, the non-generic one is not accessible
myCollection.GetEnumerator()
// the non generic one is only accessible if you cast to IEnumerable
((IEnumerable)myCollection).GetEnumerator()
Even if in the same class, you can't access the non-generic GetEnumerator without casting to IEnumerable first. Do you see how this is somewhat different from what private usually means? None of the access modifiers can really express the accessibility of explicit interface implementations, to be honest.

What does 'new' keyword mean when used inside an interface in C#?

Developing an interface generic I wished to declare a constructor in an interface but it says constructors are forbidden there. I've tried to declare a static factory method then, but it says neither static methods are allowed and suggests using 'new' keyword. But I have hardly any idea of what could 'new' keyword exactly mean when used inside an interface in C#. Have you?
UPDATE:
I didn't post any sample code because I didn't want to mix 2 questions - how to specify a constructor/factory in an interface AND what does the 'new' keyword mean in interfaces. I I even was only forced to specify the first part because StackOverflow didn't accept the second question in pure form, saying it doesn't meet quality standards.
But, as you demand, I'll sample what I was trying to acheive:
Interface IMyInterface <T, U, V>
{
IMyInterface (T, U, U);
// OR
static IMyInterface GetNewIMyInterface (T, U, U);
}
I just want every derived class to implement such a constructor.
Bala's answer is correct, but it might be helpful to see why you'd want to do this. Consider the problem that the BCL designers were faced with when designing the libraries for CLR version 2. There was an existing interface:
interface IEnumerable
{
IEnumerator GetEnumerator();
}
Now you want to add:
interface IEnumerable<T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
The new interface differs from the old solely in the return type.
What are your choices?
1) Mark the new GetEnumerator as "new" so that the compiler knows that this is intended to be the new method that does not conflict with the old method of the same name but different return type.
2) Change the name to GetEnumerator2.
3) Don't inherit from the original IEnumerable.
Options 2 and 3 are awful. Option 1 is awesome: new enumerables work seamlessly with code that expects old enumerables, but code written to use the new enumerables get the "new" generic behaviour by default.
The new keyword tells the compiler that your definition hides the definition contained in interfaces your interface might be extending.
You can't specify either a constructor or a static method in an interface... what you can do is add a type constraint for a generic type parameter, e.g.
void Foo<T>() where T : new()
{
T t = new T();
// Do stuff with t
}
Is that what you're thinking of?
An interface is supposed to specify a contract. It will only contain method signatures and no implementation. An interface cannot be instanciated directly, hence a constructor is not allowed in an interface.
http://msdn.microsoft.com/en-us/library/87d83y5b(v=vs.80).aspx
You're using an interface, but it sounds like you want a base class instead. An interface should never need a constructor, as it can't contain any fields that would need to be initialized in the constructor. I think you want to use a base class instead.
First, the only thing the 'new' keyword actually does is prompt the compiler to NOT produce a warning that you should use the 'new' keyword. Apart from getting rid of the warning, the keyword itself does nothing (in the context in question).
Now, the compiler WANTS you to use the 'new' keyword when you redefine a member (property or method) already defined in an interface you inherit from, and there are at least two possible reasons for doing this. First, as Eric Lippert mentioned above, you may want a method to return a different type (or define a property of the same name with a different type). Another possibility is if you want to define different implementations for the two interfaces:
interface A
{
void a();
}
interface B : A
{
new void a();
}
class C : B
{
void A.a() { Console.WriteLine("Called by interface A!"); }
void B.a() { Console.WriteLine("Called by interface B!"); }
}
static class Test
{
public static void DoTest()
{
B b = new C();
b.a(); // Produces "Called by interface B!"
((A)b).a(); // Produces "Called by interface A!"
}
}
If you try to define B.a() in C without redefining a() in B, you get a warning that it is not a member of interface: explicit interface declaration requires that you use an interface for which the member is explicitly defined.
C# and .NET does not allow you to declare a constructor on an interface.
It's simply got to be a stated constraint of implementing that interface (see ISerializable in the .NET libraries).
If you think about it, having a constructor on an interface doesn't make sense, as you have to know the concrete class you want to create when you call the constructor. How would you go about calling such an interface constructor, and what would the result be?

public type modifiers for interface

When a class implements an interface, the type modifiers for the interface members should be public. Why is there such a restriction?
An interface defines how other objects will communicate with objects of the type that implements that interface; Since other objects can only interact with the public properties and methods of other types, the interface must define those properties and methods as public.
There are two ways of implementing an interface method; the first is implicit implementation - which assumes the public API is exposing the interface methods, and is what you are no-doubt seeing.
However, you can also use explicit implementation:
void IDisposable.Dispose() {
// clean up
}
is a trivial example; this is private, yet satisfies the interface. An explicit implementation always takes precedence over a like-named method on the public API.
In fact, explicit implementation is often necessary, for example to implement IEnumerable<T> - since there are two conflicting GetEnumerator() methods; the following is common:
// public API will be used for implicit IEnumerable<T>.GetEnumerator()
public IEnumerator<T> GetEnumerator() { ... do work ... }
// explicit implementation of IEnumerable.GetEnumerator()
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
So: if you don't want public members; use explicit implementation.
Lets say an Interface can have Private members. When a class inherits the interface, the class will never be able to access the private member. The class will never be able to implement the private member and the program will never get compiled.

Dual enumerators, second one via interface- type collisions on implementation

I have a generic class that implements IList
public class ListBase<T>: IList<T>, IListBase{
IEnumerator<T> GetEnumerator(){ ....
System.Collections.IEnumerator GetEnumerator(){ return GetEnumerator();}
}
The IListBase is an interface I use to access methods on this class for cases where I don't know the type of T at runtime.
I need to implement a second Enumerator via this IListBase interface which will iterate the members of my class and return them cast as a base type that all members will implement.
I've tried having the IListBase implement my specific Enumerator:
public interface IListBase: IEnumerable<MemberBaseType> { ....
But this blows up due to the fact that T and MemberBaseType could be the same in some instances. Even adding the enumerator members to the interface and then using explicit declarations doesnt help this problem.
I then tried adding another method to call for just getting specific IEnumerator, but the compiler then complains about not finding a public GetEnumerator method to use with this type...
Any recommendations for adding this secondary enumerator so they don't collide with each other?
Having two enumerators at the same level that do different things is (IMO) a bad idea. You can probably force it, but as soon as someone casts your type (especially if casting to the non-generic interface) it is largely guesswork which they will get.
I would recommend (instead) making this available via a property, for example .Members, where .Members offers this enumeration. Then no ambiguity of intent, and no compiler unhappiness. So I could use:
foreach(var member in list.Members) { /* add columns */ }
foreach(var item in list) { /* add rows */ }
You might also consider ITypedList, which may have some relevence here, especially if you want to data-bind to your list (this isn't necessary if T by itself defines everything cleanly).
In short:
public interface IListBase {
IEnumerable<MemberBaseType> Members {get;}
}

Should I implement interface members explicitly or implicitly?

This question and Eric Lippert's answer got me wondering: How do you decide whether to use an explicit or implicit implementation when implementing methods of an interface?
(personally) I only see a need for explicit implementations when there is a clash between methods with the same signature.
For example, when implementing IEnumerable<T>, you should implement 2 methods GetEnumerator() which have the same signature, except for the return type. So you'll have to implement IEnumerable.GetEnumerator() explicitly:
public abstract class MyClass<T> : IEnumerable<T>
{
public IEnumerator<T> GetEnumerator()
{
return ...;
}
IEnumerator IEnumerable.GetEnumerator() // explicit implementation required
{
return GetEnumerator();
}
}
Another use for an explicit implementation is if you don't want the method to be called through an object instance, but only through an interface. I personally think this doesn't make much sense, but in some very rare cases, it can be useful.
Philippe's answer is a practical, one, however, there are architectural considerations as well.
Interfaces are used to make classes compatible so that they can be consumed by other objects. If only those consuming objects need the functionality of the interface, then it should be restricted so - by the principle of least privilege. If would be unnecessary to expose that interface method to all other users of the class.
Paul
Another case for explicit interfaces is where the object needs to implement an interface to accept calls from an internal object, but you don't want to expose those as part of your API.

Categories