First off I'm not a language lawyer, or an expert.  I am only sharing some of the impressions I've gotten from working with the real language designers.

Eric Wilson asked why C# doesn't allow you to call static methods using instance pointers.  My answer would be two-fold:

  1. C# is very explicit.  There's generally one and only one way to do a lot of things that in C/C++ had many ways.  Likewise whenever there was a C/C++ language construct that was often mis-used, misunderstood, or just confusing, the language guys tried very hard to make C# impossible to mis-use, misunderstand, or get confused.  This is such an example, see reason #2.
  2. This is confusing to someone who reads the code.  If they don't have the definition of the method nearby, they won't know it's static and thus doesn't need a valid instance pointer (which Eric's sample code lacks).  Likewise some readers might try and assume that some sort of polymorphic virtual call might happen if the instance pointer is actually some sub class.

Orangy asked why he can't derive from Delegates.  The short answer here is that it's a runtime restriction.  The runtime deals very intimately with delegates, and as such has some heavy requirements on them.  However, you can accomplish the same semantics with a little extra coding.  Basically create an intermediate class that holds a weak reference (this is not new in v2, just new to me, thanks Dmitriy) to the real delegate, then pass the intermediate delegate to the real event:

// warning untested pseudo code
sealed class WeakDelegate {
   public EventHandler MakeWeakDelegate(EventHandler realDelegate) {
      return new EventHandler(new WeakDelegate(realDelegate).WeakInvoke);
   private volatile WeakReference realDelegate; // volatile so it is thread safe
   private WeakDelegate(EventHandler realDelegate) {
      this.realDelegate = new WeakReference(realDelegate);
   private void WeakInvoke(object sender, EventArgs args) {
      EventHandler eh = this.realDelegate.Target as EventHandler;
      if (eh != null) {
         eh.Target(sender, args);


That's all for today.


[Corrected the code and some comments in response to Dmitriy's criticism]