Why can't I have protected interface members?

C#InterfaceProtectedAccess Modifiers

C# Problem Overview


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.

C# Solutions


Solution 1 - C#

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.

Solution 2 - C#

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)

Solution 3 - C#

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.

Solution 4 - C#

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.

Solution 5 - C#

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; } }
}

Solution 6 - C#

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

Solution 7 - C#

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.

Solution 8 - C#

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.

Solution 9 - C#

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

Solution 10 - C#

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://docs.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

Solution 11 - C#

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.

Solution 12 - C#

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

Solution 13 - C#

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.

Solution 14 - C#

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.

Solution 15 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionajlaneView Question on Stackoverflow
Solution 1 - C#Szymon RozgaView Answer on Stackoverflow
Solution 2 - C#Anton GogolevView Answer on Stackoverflow
Solution 3 - C#annakataView Answer on Stackoverflow
Solution 4 - C#JaredParView Answer on Stackoverflow
Solution 5 - C#Marc GravellView Answer on Stackoverflow
Solution 6 - C#Abdelrahman GamalView Answer on Stackoverflow
Solution 7 - C#Marco StaffoliView Answer on Stackoverflow
Solution 8 - C#Vojislav StojkovicView Answer on Stackoverflow
Solution 9 - C#mikeView Answer on Stackoverflow
Solution 10 - C#lidqyView Answer on Stackoverflow
Solution 11 - C#Gerrie SchenckView Answer on Stackoverflow
Solution 12 - C#Jason PunyonView Answer on Stackoverflow
Solution 13 - C#Frederick The FoolView Answer on Stackoverflow
Solution 14 - C#Brian RasmussenView Answer on Stackoverflow
Solution 15 - C#supercatView Answer on Stackoverflow