You would lose all the advantages of dynamic polymorphism which are provided by virtual calls and generics.
In the current version of C#, CountNodes
(and a hypothetical generic version CountNodes<T> where T : INode
) is compiled as a single function, where the access to the Next
property has fixed, at compile time, the offset into the v-table of the object which must be used to find the property getter. As a result, new types deriving from INode
and defined in other assemblies can be supplied to CountNodes
, since they conform to the same v-table layout.
Since the v-table layout is different between MyGraphNode
and MyLinkedNode
(they are defined without awareness of any required layout), this approach cannot work. The compiler would have to generate new and different code for each actual parameter type. This would limit you to types which existed at compile time and were known at the call site. For example, this would work:
GraphNode node = BuildGraphNodes();
int count = CountNodes(node);
but this would not:
object node = BuildGraphNodes();
int count = CountNodes(node);
Actually, this capability has already been developed. It is called C++ templates. And Microsoft provides a C++/CLI compiler that allows you to use it with .NET. It is even more powerful than the "structural interfaces" you proposed, but it easily accommodates your use case.
template<typename INode>
int CountNodes(INode^ start)
{
int i = 0;
for (INode^ current = start; current != nullptr; current = current->Next)
++i;
return i;
}
(C++/CLI works within the confines of the CLR, and does not require DLR support, quite contrary to what some commenters claimed.)
Given that this ability is already accessible to .NET developers, and would add considerable additional complexity to C#, it is unlikely to pass the cost-benefit analysis of the C# designers. So don't expect C++ templates, or even the lesser "structural interfacing", to ever be part of C#.
If you're willing to forgo all benefits of static type checking, you can use late (lookup by name, not v-table slot) binding in C# today. Just change the parameter type to dynamic
. But errors will be delayed until runtime, and performance will also take a significant hit.