87

What is the argument against declaring protected-access members on interfaces? This, for example, is invalid:

public interface IOrange
{
    public OrangePeel Peel { get; }
    protected OrangePips Seeds { get; }
}

In this example, the interface IOrange would guarantee that implementors at least provide an OrangePips instance to their inheritors. If the implementor wanted to, they could expand the scope to full public:

public class NavelOrange : IOrange
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    protected OrangePips Seeds { get { return null; } }
}

public class ValenciaOrange : IOrange
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    public OrangePips Seeds { get { return new OrangePips(6); } }
}

The intent of protected members on interfaces is to provide a support contract for inheritors (sub-classes), for example:

public class SpecialNavelOrange : NavelOrange
{
    ...
    // Having a seed value is useful to me.
    OrangePips seeds = this.Seeds; 
    ...
}

(Admittedly, this wouldn't work for structs)

I can't see much of a case for private or internal modifiers in interfaces, but supporting both public and protected modifiers seems perfectly reasonable.


I'm going to try explaining the utility of protected members on interfaces by separating them from interfaces entirely:

Let's imagine a new C# keyword, support, to enforce inheritor contracts, so that we declare things as follows:

public support IOrangeSupport
{
    OrangePips Seeds { get; }
}

This would allows us to contract classes to provide protected members to their inheritors:

public class NavelOrange : IOrange, IOrangeSupport
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    protected OrangePips Seeds { get { return null; } }
}

This is not particularly useful, because classes would already imply this contract by providing the protected members in the first place.

But then we could also do this:

public interface IOrange : IOrangeSupport
{
   ...
}

Thereby applying IOrangeSupport to all classes which implement IOrange and requiring them to provide particular protected members - which is not something we can currently do.

Charles
  • 50,943
  • 13
  • 104
  • 142
ajlane
  • 1,899
  • 1
  • 18
  • 23
  • possible duplicate of [Non Public Members for C# Interfaces](http://stackoverflow.com/questions/17576/non-public-members-for-c-sharp-interfaces) – nawfal May 11 '13 at 10:56
  • 1
    To flesh out this question, consider this use case. I have a derived class that inherits from a generic base class. I want to add a protected member that can be accessed on any of the generic flavors of the derived class, but is not exposed to the outside world. `class Base { }` `interface IDerived` `{` `string Secret { get; set; }` `}` `class Derived : Base, IDerived` `{` `protected string Secret;` `protected void LearnSecret(IDerived other)` `{` `var x = other.Secret;` `}` `}` – hypehuman Nov 04 '15 at 20:43
  • I am quite surprised that none of the answers or comments mention the EIMI. The EIMI makes the interface member private when the member is viewed through the implementing type point of view. – qqqqqqq Jan 10 '20 at 19:42
  • 1
    Might be coming in C# 8.0 https://jeremybytes.blogspot.com/2019/11/c-8-interfaces-public-private-and.html – Doug Domeny Sep 22 '20 at 14:08

15 Answers15

70

I think everyone hammered the point of an interface having only public members, no implementation details. What you are looking for is an abstract class.

public interface IOrange
{
    OrangePeel Peel { get; }
}

public abstract class OrangeBase : IOrange
{
    protected OrangeBase() {}
    protected abstract OrangePips Seeds { get; }
    public abstract OrangePeel Peel { get; }
}

public class NavelOrange : OrangeBase
{
    public override OrangePeel Peel { get { return new OrangePeel(); } }
    protected override OrangePips Seeds { get { return null; } }
}

public class ValenciaOrange : OrangeBase
{
    public override OrangePeel Peel { get { return new OrangePeel(); } }
    protected override OrangePips Seeds { get { return new OrangePips(6); } }
}

Edit: It is fair to argue that if we have a PlasticOrange that derives from a class Ornament, it can only implement IOrange and not the Seeds protected method. That is fine. An interface by definition is a contract between a caller and an object, not between a class and its subclasses. The abstract class is as close as we come to this concept. And that is fine. What you are essentially proposing is another construct in the language through which we can switch subclasses from one base class to another without breaking the build. To me, this doesn't make sense.

If you are creating a subclass of a class, the subclass is a specialization of the base class. It should be fully aware of any protected members of the base class. But if you suddenly want to switch the base class out, it makes no sense that the subclass should work with any other IOrange.

I suppose you have a fair question, but it seems like a corner case and I don't see any benefit from it to be honest.

Szymon Rozga
  • 17,971
  • 7
  • 53
  • 66
  • 11
    An abstract class only works if it is reasonable to set the base -classes of `NavelOrange` and `ValenciaOrange` to the same thing. Suppose a class `PlasticOrange` which already derives from `Ornament`. – ajlane Feb 05 '09 at 15:31
  • 5
    Then I'd doubt the orange has Seeds or can Peel. On a serious note, this is a fair point but we are constrained by the OOP single-inheritance model so I have no good answer. That being said, this solution solves the original case, unless you plan on creating the model you're hinting at. :) – Szymon Rozga Feb 05 '09 at 15:39
57

Can't see why would one want this. If you want derived class to provide an implementation of a particular method, go for abstract base classes. Interfaces are just that - interfaces. A public contract, nothing else. Think of interface as of specification which describes how should the implementation look to the outside world. A specification for a two-pin plug does not state (at least I assume that) what it's internal structure should be like. It just must be interface-compatible with a plug socket. Plug
(source: made-in-china.com)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
  • 14
    Best darned explanation I have every heard of an interface. +1 – WolfmanDragon Feb 19 '09 at 06:35
  • 8
    I think you will find it's rather important to know whether the implementation behind that plug requires a 110V or 220V current ;-) – mindplay.dk Jan 26 '12 at 17:37
  • 5
    @mindplay.dk In a perfect world plugs for 110 and 220 should be different. – Anton Gogolev Jan 27 '12 at 08:48
  • 6
    @Anton in _my_ perfect world, all devices would work equally well on 110 and 220 volts, and the _plugs_ would all be the same ;-) – mindplay.dk Jan 28 '12 at 02:50
  • 2
    Interfaces guarantee implementation for external clients. You know for sure class A will have implemented the methods of interface B if class A implements B. So you can threat A as a B and be guaranteed it will work as one. Abstract classes guarantee implementation for internal clients, classes that derive from it, but it also allows for partial implementation. It's this dual usage that is problematic. I think abstract classes should have been separated into two construct. One for partial implementation that does not allow multiple inheritance, and one for derived contract that does. – Didier A. Jan 07 '15 at 20:34
  • @didier-a, absolutely. I was drawn to this question precisely because I had been using interfaces because the lawgivers of c# won't let me do with abstract classes what they are fundamentally designed to do. – Paul Childs Jun 21 '22 at 02:48
  • Example use case of what author wants: Say you are using a base (abstract class) and you want to inject one of its child classes (which one is defined at runtime) so you are using an interface. This interface should be implemented by all child classes and therefore it is implemented in the base class(https://stackoverflow.com/questions/36376393/base-class-implementing-interface). Also, base class has some protected abstract method to enforce children to implement them. And you want to put its signature in an interface. In that case, you really wish you can have protected interface members. – Onat Korucu Jun 18 '23 at 09:57
16

Because it makes no sense. An interface is a publicly exposed contract. I am an IThing, therefore I will perform IThing methods if asked. You can't ask an IThing to confirm it performs methods it can't tell you about.

annakata
  • 74,572
  • 17
  • 113
  • 180
  • But an IThing can tell its inheritors about non-`public` methods. Why can I not ask it to perform additional IThing methods in that context? – ajlane Feb 05 '09 at 15:19
  • Because those aren't IThing methods, those are the base class's methods/properties. What if two IThing implementations implement this protected member and a third one doesn't because it just doesn't make sense. What then? – Szymon Rozga Feb 05 '09 at 15:51
  • @AJ - Confused. An IThing cannot tell it's inheritors about non-publics, that's the point right? – annakata Feb 05 '09 at 16:12
  • @siz: The third one must implement it: it's in the interface. – ajlane Feb 05 '09 at 16:34
  • @annakata: Suppose AbstractThing implements IThing and ConcreteThing derives from AbstractThing. AbstractThing can tell ConcreteThing about protected (non-public) members. The idea is that IThing could also specify some of those – ajlane Feb 05 '09 at 16:34
  • @AJ - but again that's an implementation specific detail and you can already force concrete to implement with abstract. Interfaces and Abstracts do *some* of the same things for very different reasons. – annakata Feb 05 '09 at 17:09
  • Yes, but only if abstracts make sense (or are possible) for the given classes. – ajlane Feb 05 '09 at 17:43
10

Interfaces exist to allow people to access your class without knowing what the concrete implementation is. It completely divorices the implementation from the data passing contract.

Therefore, everything in an interface must be public. Non-public members are only useful if you have access to the implementation and therefore don't meaningfully contribute to an interface definition.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
10

Since C# 8.0 (September 2019) You can have an access modifier inside the interface

Check these changes in interface c# 8.0

Update interfaces with default interface methods in C# 8.0

See these posts

C# 8 Interfaces: Public, Private, and Protected Members

A Closer Look at C# 8 Interfaces

Abdelrahman Gamal
  • 470
  • 1
  • 5
  • 15
8

Interface members are a public API; things like protected etc are implementation details - and interfaces don't have any implementation. I suspect what you are looking for is explicit interface implementation:

public class NavelOrange : IOrange
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    OrangePips IOrange.Seeds { get { return null; } }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Explicit interface implementations are still `public`, so it's not really what I'm looking for. Specifically, I'm thinking `protected` members would provide an API between sets of base classes and their inheritors. – ajlane Feb 05 '09 at 15:13
  • That is strictly between the base-class and the inheritor - it simply has nothing what-so-ever to do with the interface. If you want a protected method in the base-class, simply declare one. – Marc Gravell Feb 05 '09 at 15:27
  • Right, but suppose we have a broad range of base-classes implementing the interface. It seems reasonable to define a contract which says that anyone deriving from those classes can expect a certain standard of support. – ajlane Feb 05 '09 at 15:35
3

An interface is just like the shape of a key.

enter image description here

It's not the key.

It's not the lock.

It's just the slim contact point.

For this reason all the members of the interface (that defines the shape of the key) must be public.

For a key to open a lock it is important that they both share the same shape.

By making the shape (the interface) public, you can let others create compatible locks or compatible keys.

Otherwise, making it (the interface) internal you will not allow others to create compatible locks or compatible keys.

Marco Staffoli
  • 2,475
  • 2
  • 27
  • 29
  • In your diagram, all the contact points are internal. There's no reason for the contact points to always be public. C# just makes it that way. – Suncat2000 Feb 18 '21 at 21:15
  • Someone said that the previous answer is the best damn explanation of interfaces but I disagree. This one is more concise and clearer. – Paul-Sebastian Manole Sep 19 '21 at 20:44
3

Just for the record: As of C# 8.0 interfaces now can contain

  • protected members
  • private members
  • implementation

Which as a bottom line introduces some features previously only available in languages that support multiple inheritance such as sharing implementation of multiple base members.

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/default-interface-methods-versions https://jeremybytes.blogspot.com/2019/11/c-8-interfaces-public-private-and.html

lidqy
  • 1,891
  • 1
  • 9
  • 11
1

An interface is a contract that promises certain functionality to clients. In other words, the purpose of an interface is to be able to cast a type into it and pass it around like that to code that needs the features guaranteed by that interface. Since client code of a type cannot access protected members of that type, it makes no sense to declare protected items in an interface.

Vojislav Stojkovic
  • 8,043
  • 4
  • 35
  • 48
1

in contrast to abstract base classes, protected interfaces would allow "multiple inheritance" (of abstract classes), which i would have found useful once or twice...

mike
  • 1,627
  • 1
  • 14
  • 37
0

Any class which implements a .net interface will have to include implementations of all of the interface members. Further, any class can expose to a derived class whatever members it wishes. Requiring that an implementation of an interface must include a member which will only be usable from derived classes would serve no useful purpose, unless either (1) such a member could be visible to something outside the interface, or (2) interface implementations could use members which they did not themselves define. If interfaces were allowed to include nested classes (which could access the interfaces' protected members), then protected interface members would make sense. Indeed, they could be very useful if a class nested within an interface could define extension methods for that interface. Unfortunately, no such facility exists.

BTW, even without being able to nest classes in interfaces, it would still be useful to apply an internal access modifier to interface members, with the effect that only the assembly where the interface is defined would be able to define any implementations for it.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • It would be very useful to restrict an interface member to derived classes. That way, it's the implementation that's responsible for how to expose it publicly or not. The interface doesn't allow defining the scope, so it really should be up to the implementing class. If I wanted a class member to expose a typed interface member as the type _or its derivative_, that should be up to me in the class, not the interface. It sucks being prevented from doing that. – Suncat2000 Feb 18 '21 at 21:22
  • If casting a derived-class reference to a base class type and then to an interface would allow invocation of an interface member, then casting a base-class reference to the interface type would also have to be expected to allow invocation of that member. If the interface member could only be used when a derived-class reference was cast to the interface type, then code which has a base-type reference to a derived-class object and wants to use the interface, method would have to cast to the correct derived type, which would defect the purpose of using the interface. – supercat Feb 18 '21 at 22:05
0

An interface is all about what a certain object can do, so when using a class which implements that interface the developer will expect all the members to be implemented, so the protected access modifier won't mean anything for interfaces.

Gerrie Schenck
  • 22,148
  • 20
  • 68
  • 95
  • 1
    Agreed, but I'm not so much asking why implementing members of an interface can't be optional (as they should not), but why I can't specify their level of access. – ajlane Feb 05 '09 at 14:45
0

An Interface contains only public members. Protected means whatever you're declaring is only available to the class and derived class instances.

Restore the Data Dumps
  • 38,967
  • 12
  • 96
  • 122
0

There's sound judgment in current design of interfaces which is that it offers implementers greater flexibility. Remember that very often interfaces are written by framework programmers and implementers are different folks. To enforce implementation would be needlessly harsh.

G S
  • 35,511
  • 22
  • 84
  • 118
0

By implementing an interface the type states that it supports a specific set of methods. If any of these methods were not public, it would not be available to callers and thus the type would not support the interface as stated.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317