Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't an interface contain types?

Tags:

c#

This has caught me out once or twice in C#. I can write code such as this

class Node
{
    class Connection
    {
        public Connection(Node node, string label)
        {
            this.Node = node;
            this.Label = label;
        }
        public Node Node { get; private set;  }
        public string Label { get; private set; }            
    };

    IEnumerable<Connection> IncomingConnections() // ...
    IEnumerable<Connection> OutgoingConnections() // ...
}

but if I write

interface INode
{
    class Connection
    {
        public Connection(INode node, string label)
        {
            this.Node = node;
            this.Label = label;
        }
        public INode Node { get; private set; }
        public string Label { get; private set; }
    };

    IEnumerable<Connection> IncomingConnections();
    IEnumerable<Connection> OutgoingConnections();
}

I get the compile error

error CS0524: 'Connection': interfaces cannot declare types

I understand the restriction, but what I'm interested in is why. I can certainly have nested types in a C++ "interface" (which is just a class with abstract members so no surprise), and apparently it's possible in Java too, see Interfaces Cannot Declare Type Issue C#. So given that C# learnt some things from Java, why is it lacking in this respect (if indeed it is lacking)?

(Apologies if this has already been addressed elsewhere. I also found Interfaces cannot declare types and Why can't I put a delegate in an interface? but they didn't seem to address my question directly.)

Edit

I thought I'd just add a note to say that in the Java world it seems at first sight to be an open question as to whether it's ok to nest a class within an interface. See https://stackoverflow.com/a/9098321/834521. I don't think I'm being silly in asking why the same can't apply to C#.

Edit

Brief summary / quotes from Framework Design Guidelines, 2ed, section 4.9 pp115-117.

  • Do use nested types when e.g. the nested type needs access to private members of the enclosing type.
  • Don't use public nested type for grouping; use namespaces for this.
  • Avoid publicly nested types unless you really know what you're doing. (Main motivation: explicitly creating nested types is confusing for less skilled developers. However implicitly creating, e.g. via collection enumerators, is ok.)
  • Don't use nested types if the nested type is it is going to be used or instantiated outside of the containing type (both of these argue for independence of the nested type from the containing type).
  • Don't use as a member of an interface.
like image 812
TooTone Avatar asked Apr 22 '13 16:04

TooTone


People also ask

Why interface Cannot contain fields?

By default all the members of Interface are public and abstract. The interface will always defined with the help of keyword 'interface'. Interface cannot contain fields because they represent a particular implementation of data. Multiple inheritance is possible with the help of Interfaces but not with classes.

Can an interface be a type?

When you define a new interface, you are defining a new reference data type. You can use interface names anywhere you can use any other data type name.

Which Cannot be included in an interface?

An interface cannot contain instance fields. The only fields that can appear in an interface must be declared both static and final. An interface is not extended by a class; it is implemented by a class. An interface can extend multiple interfaces.

Can interface contains methods?

The interface body can contain abstract methods, default methods, and static methods. An abstract method within an interface is followed by a semicolon, but no braces (an abstract method does not contain an implementation).


1 Answers

Would like to add, that from C# 8.0, interface is permitted to use nested types.

Default interface methods - C# 8.0 specification proposals | Microsoft Docs (emphasis added)

The syntax for an interface is extended to permit:

  • member declarations that declare constants, operators, static constructors, and nested types;

So something like below is now legal.

interface ISpectrum {
    [Flags]
    enum Palette { Red = 1, Green = 2, Blue = 4 }
    Palette Color { get; }
}

Whether this is good practice has been discussed in other answers, but I personally find interface-specific enum has its uses.

Interestingly, despite this change being listed as being part of the default interface implementation, most of which requires new runtime i.e. .NET Core 3.0/.NET Standard 2.1 and later, interface with nested type but without any implementation does compile and can be used in .NET Framework 4.8, as long as Roslyn CSC supporting compilation in C# 8.0 is used.

I assume this is due to the fact that CLR has been supporting nested type in interface for all this time, as Eric Lippert stated in the answer here.

like image 74
shinfd Avatar answered Oct 28 '22 12:10

shinfd