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.
Connection
on the interface, but the implementation of that type is going to be described elsewhere. Imagine if you had to refer to that particular interface every time you needed to create an object of typeConnection
. That would be pretty awkward, wouldn't it?