3

Why am I not allowed to implement an internal interface in an internal class? Is there a specific reason for this restriction or is it just a language design decision?

internal interface IDefinition
{
    string GetValueAsString(string property);
}

internal sealed class DefinitionArray : IDefinition
{
    internal string GetValueAsString(string property)
    {
        return m_definitionRows
            .Select(o => o.GetValueAsString(property))
            .FirstOrDefault();
    }
}
Vahid
  • 5,144
  • 13
  • 70
  • 146
  • 3
    Because that's the way the language was designed. Properties and methods defined in the interface must be implemented as `public` in types that implement that interface. As long as your class is still `internal`, you don't need to worry about other assemblies accessing it anyway. – itsme86 Nov 28 '17 at 23:42
  • 4
    Possible duplicate of [C# internal interface with internal implementation](https://stackoverflow.com/questions/6117386/c-sharp-internal-interface-with-internal-implementation) – Kenneth K. Nov 28 '17 at 23:42
  • @itsme86 But why? Any logical reason? – Vahid Nov 28 '17 at 23:43
  • 1
    I'm sure there is. Who are we to know the minds of The Great Designers? – itsme86 Nov 28 '17 at 23:44
  • @itsme86 Nobody if we do not stay curious! – Vahid Nov 28 '17 at 23:45
  • It's been asked before. @KennethK. gave one example. Here's another one: https://stackoverflow.com/questions/7238575/why-must-an-c-sharp-interface-method-implemented-in-a-class-be-public – itsme86 Nov 28 '17 at 23:45
  • @itsme86 Thanks for the link. – Vahid Nov 28 '17 at 23:46
  • Have you tried making the implementation of GetValueAsString public? The interface method is public so the implementation should be too. The interface itself, and the class can still be internal, so the effect should still be what you want. – hatchet - done with SOverflow Nov 28 '17 at 23:48
  • @hatchet Of course public works. I was expecting that since the interface is marked as internal, the Implementation should be internal! – Vahid Nov 28 '17 at 23:51
  • 1
    @hatchet I think OP knows how to fix it. They're just wondering why it's a requirement. If the visibility of the interface is `internal`, why should the implementations need to be `public`? – itsme86 Nov 28 '17 at 23:51
  • That wasn't clear at all from the title and question. It only talked about the interface and the class, not the method. – hatchet - done with SOverflow Nov 28 '17 at 23:52
  • @hatchet Why can't I implement an internal interface in an internal class? I think this single sentence is enough even without the code! – Vahid Nov 28 '17 at 23:53
  • 1
    You **can** implement an internal interface in an internal class. By changing the **method** visibility to public. What you can't do is implement a public interface method with an internal implementation. – hatchet - done with SOverflow Nov 28 '17 at 23:56
  • 1
    @hatchet That's what the OP wants to know. interface members must be `public`. Why can't you change their visibility to `internal`? You say "public interface method" like it's an option, but there's no way to change an interface method to not be `public`. – itsme86 Nov 29 '17 at 00:01
  • It doesn't matter whether you declare the member as `public` or `internal` - the class is `internal` so the member is effectively `internal` even if it's declared `public`. – Blorgbeard Nov 29 '17 at 00:03
  • 1
    @Blorgbeard Exactly. That's what I was saying in my very first comment. It is interesting though in the "story that's told" sense of things. Some code maintainer down the line might see the `public` method and wonder "did they mark it `public` just because of the interface restriction or for another reason?" – itsme86 Nov 29 '17 at 00:06
  • @Blorgbeard It matters if you start messing around with Reflection – Matias Cicero Nov 29 '17 at 00:06
  • Personally, I tend to consider `public` members only public relative to their class visibility, so I would make that member public by default anyway. And @MatiasCicero I don't see how - if you use reflection, it doesn't matter what the visibility is anyway. – Blorgbeard Nov 29 '17 at 00:09
  • 1
    Also, consider if the class was `public` but you wanted to have a method that could only be used internally. The interface could be `internal` but you'd be forced to implement the interface members in the `public` class as `public` making it impossible to accomplish your goal. I'm not prepared to argue that that would be a "well designed" class, but it seems like something that should be doable. Where's @ericlippert when you need him? ;) – itsme86 Nov 29 '17 at 00:17
  • @itsme86 you could implement the internal interface explicitly. – Blorgbeard Nov 29 '17 at 00:54
  • 1
    @Blorgbeard You could, but it definitely feels like a "work around" to me. – itsme86 Nov 29 '17 at 01:26

2 Answers2

4

§3.5.6 of the C# 6.0 Language Specification states:

Interface members implicitly have public declared accessibility. No access modifiers are allowed on interface member declarations.

So what you 'theoretically' have is

internal interface IDefinition
{
    public string GetValueAsString(string property);
}

But this is not a problem, since (§3.5.2):

The accessibility domain of a nested member M declared in a type T within a program P is defined as follows (noting that M itself may possibly be a type):

  • If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.

So the accessibility of the member is equivalent as it would have been declared as internal.

adjan
  • 13,371
  • 2
  • 31
  • 48
  • 2
    This totally misses the question of *why* the decision was made to disallow access modifiers on interface members. I can't think of any logical reason why an internal interface couldn't have its implemented members marked *at least as accessible* (i.e. `internal` or `public`) as the interface's visibility. – itsme86 Nov 29 '17 at 00:14
1

The members that make up the Interface's implementation must be public. Even if they are public since the class is internal it's only available to the proper assembly.

Immac
  • 466
  • 1
  • 5
  • 16
  • Yes it is true but that is strange that the compiler cannot detect the interface is internal and is basically invisible to the outside world! Then why does it matter that it does not let you mark your methods in the internal class as internal! – Vahid Nov 29 '17 at 07:33