Quiz: More Type Constructors


The program below outputs “in .cctor” when run.  In the spirit of NPR’s Says You, make a 6 character change to only line 10 that will allow the program to continue to compile without warnings or errors but when run result in no output. Any of course, why?

 

 

  00   using System;

 01   public class Program

 02   {

 03       static void Main(string[] args)

 04       {

 05         Type1 t = new Type1();

 06       

 07       }

 08   }

 09         

 10   public class  Type1

 11   {

 12       static Type1()

 13       {

 14           Console.WriteLine (“in .cctor”);

 15       }  

 16   }

Comments (12)

  1. Vladimir Yangurskiy says:

    Replace "class" by "struct" ?

  2. Serdar Kilic says:

    The docs say that structs cannot have parameterless constructors, but why ?

  3. Lawrence Pina says:

    When implemented as a class, the type constuctor gets fired when any method or field is accessed because it is not marked beforefieldinit.

    Since when implemented as a class, a default instance constructor is supplied and called when an instance of the class is declared. Calling the default class constructor causes the type constructor to be called, resulting in the WriteLine statement being called.

    When implemented as a struct, there is no defualt instance constructor created, so when the type is created, no field in the class has been accessed, nor any method has been called, so the type constructor will not be called. No WriteLine!

    That’s my guess.

    Lawrence

    lpina@colada.com

  4. Shawn says:

    If this is Whidbey, why not make this a static class?

    public static class Type1

  5. Lawrence Pina says:

    I the example, he created an instance of the type from the Main method. You can not create an instance of a static class.

  6. I cheated a little, and built this. (Shouts out to Jeff Key for making it easy to test this things with <a href="http://www.sliver.com/dotnet/SnippetCompiler/">SnippetCompiler</a&gt;, and Lutz Roeder for .Net reflector).

    The answer is indeed to change the class to a struct. But looking at the IL, there is absolutely no difference in the type constructor emitted by the compiler, be it a class or a struct. So the CLR must decide when to call the constructor.

    If you put a method on the struct, and then call the method, the static constructor gets called just before the method. For the class, the static constructor is called when the class is first initialized. Maybe this is because the class has a default constructor, and the struct doesn’t.

    But it goes along with what Jeff Richter said about type constructors in his "Applied .Net framework" book – you can’t rely on a specific time for the type constructor to be called. It depends on the CLR.

    Great question. I’m really getting into these quizes now.

  7. Mads Houmann says:

    Replace class with struct. This is because value types are always marked with the beforefieldinit optimization meaning that cctor execution can be deferred until first access to a static field.

  8. Well, changing Type1 from being a class to a being a struct, causes the compiler to not emit a default instance constructor for MyType, as it does implicitly for classes.

    When constructing an instance of a reference type (class Type1), the compiler calles the constructor (newobj …). The static constructor is supposed to fire before any of the class’ code is run, so it fires before the code in the instance constructor is executed.

    Instances of value types (struct Type1) are created by a initobj instruction. No constructor code is executed, so there is no need for the static constructor to run.

    If one adds an explit instance constructor (f.i. MyType(bool dummy)) to the struct definition and uses that to create an instance, the static constructor _will_ run.

    BeforeFieldInit relaxes the constraint that static-constructor code should run before any of the types other code, but has nothing to do with this example. (C# uses it for combined declaration and initialization of static fields, for example.)

  9. Daniyaal says:

    I’ve VS 2003 and its compiling the code without any errors.

  10. Stefan Holdermans says:

    No one said there’d be any errors.

  11. structs cannot have parameterless ctors because of the resulting hidden cost of array allocation, e.g.

    struct Point

    {

    public Point()

    {

    System.Threading.thread.Sleep(1000);

    }

    }

    static void Main()

    {

    // this line will take more than a day to execute

    Point[] ps = new Point[100000];

    }

    ref types don’t have this problem as the array allocation is simply an array of references not the instance itself.

  12. Stefan Holdermans says:

    Furthermore, value types can well by obtained by interaction with unmanaged code. Then there is no way to guarantee that constructor code has been run.