Generic Properties

published: Tue, 25-Nov-2003   |   updated: Thu, 27-Oct-2005

Last week I organized a chat for the Visual C# team on MSDN. It's something we do once a month (currently the third Thursday of every month) to answer questions posed to us by customers. An hour of fun stuff: we generally get a good cross-section of the team's Program Managers, developers, and QA. Last week we even had our Product Unit Manager (PUM), Scott Wiltamuth, as well.

Anyway, last week's chat included a question about generics that I hadn't heard before: why aren't you going to have generic properties? Let's investigate. (For information on our generics support, visit MSDN's Visual C# site.)

The generics support in C# 2.0 is going to include generic methods, so we could write this kind of code:

public T GetThing<T> {
  //do something to get a T and return it
}

public void SetThing<T>(T value) {
  // do something with the passed in T 
}

It seems as if we have enough to write a property now:

private T thing;

public T Thing<T> {
  get { return thing; }
  set { thing = value; }
}

However there's an implicit problem here: we've separated the backing store from the property. Unfortunately in doing so, this won't compile: T is only a placeholder for some other type, the type that'll be passed in the type parameter for the property. The backing store has no type parameter, T is meaningless for the field. We can't give it one because we don't support that either in C# 2.0. However, imagine for a moment that we had a contextual keyword much like value, called field, perhaps. We could write the property like this:

public T Thing<T> {
  get { return field; }
  set { field = value; }
}

The compiler would do the right thing and emit IL to cause the jitter to create a backing store of the right type whenever it compiled this kind of code. Sounds done, eh? Not quite so fast; check out this code that uses this property:

public class Foo {
  public T Thing<T> {
    get { return field; }
    set { field = value; }
  }
}

...
Foo f = new Foo();
f.Thing<int> = 7;
f.Thing<string> = "Hello, Crash";

Looks OK? Now think about it from the compiler's viewpoint. First a Foo object has to be allocated on the heap. No problem, right? Well, unfortunately, yes. How big is a Foo? It has a generic property. We must reserve space for the backing store for the generic property (it's part of the Foo class). But we don't know how much to reserve. Even if the compiler had read and understood every possible use of the generic Thing property and worked out how many instantiations there were, even in the code we will write ten years in the future, we could still use reflection to bind a type to the property at run-time.

Hence, it's impossible for the compiler to say how big a Foo object is. Even the jitter couldn't work it out at run-time. So, no generic properties because we can't even cater for the simplest case.