Skip to content

Two structural additions to C#

In What’s in a name? (C#’s hidden support for structural typing) we explored a few of the areas in which C# currently supports structural typing. I would like to propose two new additions to C#’s structural typing abilities: implicit interface inheritance and richer generic constraints.

Implicit interface inheritance

I propose that class or struct ought to be able to implicitly inherit from an interface if the two are structurally equivalent in every way. The idea is that if a type has all the members of an interface it can claim implicit inheritance of that interface making examples like this legal:

using System;
using System.Collections;
interface IName { String Name { get; } } class Example { static void Main() { printName(new { Name = "Nic" }); } static void printName(IName name) { Console.WriteLine(name.Name); } }

Allowing any type to implicitly implement an interface would open many opportunities. First, it would encourage the use of anonymous types for message passing between methods thereby avoiding the need to declare a type.

Second, now the fact that interfaces would offer even more flexibility, developers would be encouraged to choose interfaces for their method parameter types (i.e. program to an interface).

Richer generic constraints

Currently, C# only supports new() as a generic constraint for type constructors. This constrains the type parameter to only those types that have parameterless constructors. This means that if you want to instantiate an instance of a generic type argument you are forced to use reflection to do so:

using System;
class Foo { public Foo() { } public Foo(String name) { } } class Example { static void Main() { Foo f = create<Foo>(); } static T create<T>() where T : new() { Object instance = Activator.CreateInstance(typeof(T), new[] { "Foo" }); return (T)instance; } }

While Activator.CreateInstance is a very useful method, it does use reflection and any incompatibility between the constructor of the type and the arguments passed to it will cause an exception to be thrown. I propose that C# incorporate a new type of generic constraint for constructors that allow developers to specify the signature of the constructor like this:

using System;
class Foo { public Foo() { } public Foo(String name) { } } class Example { static void Main() { Foo f = create<Foo>(); } static T create<T>() where T : new(String) { return new T("Foo"); } }

If the generic type argument has a constructor that matches the structure of the generic type constraint it should satisfy the constraint. This will allow richer generic programming as we will be able to instantiate many different types of objects without sacrificing type-safety.

So what do you think? Are there other areas that C# could implement structural typing that would be beneficial?

4 Comments

  1. Paul

    I like the idea of better new() constraints. Vote for it here if you think so too: https://connect.microsoft.com/VisualStudio/feedback/details/90900/c-language-allow-argument-types-in-generic-new-constraint

    Posted on 28-Apr-10 at 11:48 pm | Permalink
  2. Roman

    The very first example is appealing- mocking comes to my mind-, but I believe there are things to consider like methods inside interfaces. In such case, how would you go about implementing such methods? As a delegate? What the syntax would be?

    Posted on 09-Jun-10 at 9:18 am | Permalink
  3. That’s an excellent question! This concept would hopefully support all types, not just anonymous types. That means that any type that is structurally equivalent would implicitly implement the interface. This would be helpful with working with 3rd party types that don’t implement interfaces that you wish they did. As for anonymous types, they would never be able to implicitly implement any interface that had methods since anonymous types cannot be declared with methods.

    Posted on 09-Jun-10 at 3:22 pm | Permalink
  4. Stands back from the kybeorad in amazement! Thanks!

    Posted on 13-Apr-11 at 12:07 am | Permalink

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*