Disclaimer: This is a personal web page. Contents written here do not represent the position of my employer.

Wednesday, February 04, 2009

 

My first .NET runtime wishlist item

Heh, I came up with this while coding a patch for Banshee:


public class TestStaticInits
{
  public static readonly X var = new X ("Hello" + world);
  private static string world = " World";
}

public class X
{
  public X (string s)
  {
    Console.WriteLine (s);
  }

  public override string ToString () { return "Bye"; }
}

public class WishList
{
  public static int Main(string[] args)
  {
    Console.WriteLine (TestStaticInits.var.ToString ());
    return 0;
  }
}


Shouldn't this print Hello World instead of just Hello? Basic initializations should have more priority than those involving constructors :)

At least it works if you replace the second static with const... But this confused me a bit for a while. So definitely something the compiler could warn about (ok, Gendarme is another candidate too).

UPDATE: And anyway, if we accept that our runtime is not so clever, it should give a NRE instead of printing Hello, right? You cannot concatenate a string with null. So is this a .NET bug?

UPDATE: Doh! I could have sworn that I got a lot of NRE's in the past when coding this Console.WriteLine ("Hey" + null); (I mean, when using a var and not protecting against null). Thanks for all the comments.

Labels: , , ,


Comments:
There can be no ordering of initialization of statics that satisfies all scenarios: what if there was a cycle in the dependencies? Not all dependencies can be calculated due to the limits of code analysis, aka the halting problem, since the initializers can call arbitrary static methods.

Static initializers are handled in a predictable fashion, rather than trying to achieve the impossible. They are executed in order, as if they were injected into the start of a class constructor.

Constants are different, because they are baked into their use sites; this means they need to be evaluated by the compiler, which in turn means an ordering can be calculated for them, with a diagnostic on a cycle. This isn't problematic because the initializer for a constant can't be e.g. a constructor call or static method call; the compiler needs to be able to evaluate it at compile time (in order to bake-in uses), so it can easily discover any cycles.

And finally, contrary to what you think, it is perfectly possible to concatenate as many null strings as you like. Try this on for size:

string x = (string) null + (string) null + (string) null;

No errors, no problems, and x is an empty string afterwards.

Finally, don't declare variables called var. It conflicts with the pseudo-keyword "var" :)
 
http://www.jaggersoft.com/csharp_standard/17.4.5.htm
"2 Thus, when a class is initialized, all static fields in that class are first initialized to their default values, and then the static field initializers are executed in textual order."

So put the 'world' field first and one sees Hello World. Seems that simple rule is better than anything more complex. :-)


There's also no problem with concatenating a string with null.
http://msdn.microsoft.com/en-us/library/a6d350wd.aspx "An Empty string is used in place of any null argument."
 
This way:
public class TestStaticInits
{
private static string world = " World";
public static readonly X var = new X("Hello" + world);
}

works (prints "Hello World")

McHack
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?

Categories

RSS of the category Gnome
RSS of the category Mono
RSS of the category C#
RSS of the category Programming
RSS of the category Mozilla
RSS of the category Web Development
RSS of the category Security
RSS of the category Open Source
RSS of the category Engineering
RSS of the category Misc
RSS of the category Politics

Contact with me:
aaragonesNOSPAMes@gnNOSPAMome.org

Archive
My Photo
Name:
Location: Hong Kong, Hong Kong
Follow me on Twitter