Thursday, April 28, 2005

With Don Box doing all manner of crazyness with anonymous delegates recently, I decided to do some experimenting of my own. While doing so, I ran into an interesting problem.  I was toying with a robust action scheduling mechanism that serializes actions to disk to make sure that they won't be lost in the case where the host process is stopped for some reason.

I was using the generic Action delegate to represent the actions and using anonymous delegates to inject things like action rescheduling.  I was pleased to see that basic anonymous delegates were serialized without issue.  But, when I started to use the closure features of anonymous delegates, it stopped working.  I was dissapointed, especially when I figured out why.

When you create an anonymous delegate without using outer variables, it is hoisted into the enclosing class as a private method with a compiler-generated name (that appears to be generated based on a combination of the signature and some randomness).  For example:

[Serializable]
public class Example {
  void Test() {
    Action action = delegate(DateTime scheduledTime) {
      Console.WriteLine("blah");
    };
  }
}

This actually turns into something like:

[Serializable]
public
class Example {
  void Test() {
    Action action = new Action(CompilerGeneratedName);
  }

  void CompilerGeneratedName(DateTime dateTime) {
    Console.WriteLine("blah");
  }
}

Actually, it does some niftyness to cache the delegate, but that's not important for this example. As you can see, serialization isn't a problem here.  However, if you use an outer variable within the method, the compiler hoists both the method and the variable into a nested class so it's available later when the delegate actually runs.  For example:

[Serializable]
public
class Example {
  void Test() {
    string foo = "blah";
    Action action = delegate(DateTime scheduledTime) {
      Console.WriteLine(foo);
    };
  }
}

This turns into something like:

[Serializable]
public
class Example {
  void Test() {
    CompilerGeneratedClassName something = new CompilerGeneratedClassName();
    something.foo = "blah";
   
Action action = new Action(something.CompilerGeneratedName);
  }

  private class CompilerGeneratedClassName {

    public string foo;

    void CompilerGeneratedName(DateTime dateTime) {
      Console.WriteLine(foo);
    }
}

Pretty cool, eh? Yeah, so what's the problem?  Well, the nested class is not marked with SerializableAttribute, so it can't be serialized, which makes the delegate serialization fail.  This seems like a big problem to me.  There may be a legitimate reason for this, but I don't see it.  I think the compiler ought to decorate the nested class if the enclosing class is also decorated.

There may be a way around this, but I haven't found it yet.  Any suggestions?

[Update] If you think this is a problem too, then vote for it.

posted on Thursday, April 28, 2005 5:55:08 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
Related posts:
9-year Anniversary (yesterday)
LinqToStdf now on CodePlex
Image Slicer for Deep Zoom in Silverlight 2
Silverlight limitations and Constrained Callvirt in IL
Happy Birthday Peter
What are the generic Delegates in the framework for?
Tracked by:
"Canada wanted psychic readers Canada" (Canada wanted psychic readers Canada) [Trackback]
"grand theft auto sanandreas cheat codes" (grand theft auto sanandreas cheat cod... [Trackback]
"beach scene" (beach scene) [Trackback]
"used boat yamaha" (used boat yamaha) [Trackback]
"adult massage queens craiglist" (adult massage queens craiglist) [Trackback]
"closet layout" (closet layout) [Trackback]
"standardbred canada" (standardbred canada) [Trackback]
"casio keyboards" (casio keyboards) [Trackback]
"virginia bass boat dealers" (virginia bass boat dealers) [Trackback]
"the poem poor girl" (the poem poor girl) [Trackback]
"filthy white bitch" (filthy white bitch) [Trackback]
"Orlando%2C FL" (Orlando%2C FL) [Trackback]
"renovation hardware" (renovation hardware) [Trackback]
"shooting bench" (shooting bench) [Trackback]
"hunting south dakota" (hunting south dakota) [Trackback]
"hsbc internet banking" (hsbc internet banking) [Trackback]
"alarm systems arlington" (alarm systems arlington) [Trackback]
"online psychic chat" (online psychic chat) [Trackback]
"SIP IP Handset" (SIP IP Handset) [Trackback]
"grand cherokee" (grand cherokee) [Trackback]
"snuff hogtied chloroformed video" (snuff hogtied chloroformed video) [Trackback]
"vero beach%2C fl" (vero beach%2C fl) [Trackback]
"Zeta Phi Beta Sorority Incorporated" (Zeta Phi Beta Sorority Incorporated) [Trackback]
"modern holiday cards" (modern holiday cards) [Trackback]
"Business Card Holders" (Business Card Holders) [Trackback]
"luxury wheels" (luxury wheels) [Trackback]
"homes for sale in nashville" (homes for sale in nashville) [Trackback]
"timeshares hawaii" (timeshares hawaii) [Trackback]
"Last Minute Flights" (Last Minute Flights) [Trackback]
"ekoostic hooka" (ekoostic hooka) [Trackback]
"Illinois Wedding Limo" (Illinois Wedding Limo) [Trackback]
"DYNAMARK 12 HP 39" (DYNAMARK 12 HP 39) [Trackback]
Name
E-mail
(will show your gravatar icon)
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):