BUG in static constructors?!?!?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Sunny

    BUG in static constructors?!?!?

    Hi all,
    According C# Language Specification :

    10.11 Static constructors:

    The static constructor for a class executes at most once in a given
    application domain. The execution of a static constructor is triggered
    by the first of the following events to occur within an application
    domain:
    - An instance of the class is created.
    - Any of the static members of the class are referenced.

    Then can someone confirm that the following code does not act as it
    should (seems like a bug), i.e. static constructor is NEVER called.

    Pls, note that if you uncomment the first line in Main(), everything
    runs as expected.

    Also, my environment is VS.Net 2003/framework 1.1.

    Thanks
    Sunny

    CODE (watch out for line wraps):

    using System;
    using System.Net;
    using System.IO;

    namespace TestApp
    {
    class TestApp
    {
    [STAThread]
    static void Main(string[] args)
    {
    //MyChildClass.Th eString = "Set";
    MyChildClass.Do Something();
    Console.WriteLi ne("Press enter to continue");
    Console.ReadLin e();
    }
    }

    public abstract class MyBaseClass
    {
    protected delegate void DoSomethingDele gate();

    protected static DoSomethingDele gate DoSomethingFunc ;

    protected static string SomeString = "N/A";

    public static void DoSomething()
    {
    Console.WriteLi ne("MyBase.DoSo mething()");
    DoSomethingFunc ();
    }
    }

    public class MyChildClass : MyBaseClass
    {
    static MyChildClass()
    {
    Console.WriteLi ne("static MyChildClass()" );
    DoSomethingFunc =
    new DoSomethingDele gate(DoSomethin gImpl);
    }

    protected static void DoSomethingImpl ()
    {
    Console.WriteLi ne("DoSomething ()");
    }

    public static string TheString
    {
    get{return SomeString;}
    set{SomeString = value;}
    }

    }
    }

  • Richard A. Lowe

    #2
    Re: BUG in static constructors?!? !?

    DoSomething() is a member of MyBaseClass, even though C# allows you to
    access it via MyChildClass. Therefore no member of MyChildClass is
    referenced. I actually like this behaviour, because it gives you more
    granular control over static constructor execution for 'lazy' construction
    of singletons etc. What I'm not certain I like is C# giving you access to a
    public static member of a base type, when it removes all reference to the
    type your are specifying in the IL (I looked and MyBaseClass gets called in
    the IL, so it's definately C# doing this). I'll have to look up where this
    behaviour is specified, as maybe there's a clue as to why it's this way.

    But anyway, keep in mind there are other constructs in which you can refer
    to MyChildClass that don't result in the static constructor being fired, as
    well, i.e. typeof(MyChildC lass), so I ultimately I think it's fair that base
    class members should not cause the constructor to fire.

    Richard

    --
    Veuillez m'excuser, mon Français est très pauvre. Cependant, si vous voyez
    mauvais C #, c'est mon défaut!
    "Sunny" <sunnyask@icebe rgwireless.com> wrote in message
    news:MPG.1a0edb 482e3a06ce98969 9@msnews.micros oft.com...[color=blue]
    > Hi all,
    > According C# Language Specification :
    >
    > 10.11 Static constructors:
    >
    > The static constructor for a class executes at most once in a given
    > application domain. The execution of a static constructor is triggered
    > by the first of the following events to occur within an application
    > domain:
    > - An instance of the class is created.
    > - Any of the static members of the class are referenced.
    >
    > Then can someone confirm that the following code does not act as it
    > should (seems like a bug), i.e. static constructor is NEVER called.
    >
    > Pls, note that if you uncomment the first line in Main(), everything
    > runs as expected.
    >
    > Also, my environment is VS.Net 2003/framework 1.1.
    >
    > Thanks
    > Sunny
    >
    > CODE (watch out for line wraps):
    >
    > using System;
    > using System.Net;
    > using System.IO;
    >
    > namespace TestApp
    > {
    > class TestApp
    > {
    > [STAThread]
    > static void Main(string[] args)
    > {
    > //MyChildClass.Th eString = "Set";
    > MyChildClass.Do Something();
    > Console.WriteLi ne("Press enter to continue");
    > Console.ReadLin e();
    > }
    > }
    >
    > public abstract class MyBaseClass
    > {
    > protected delegate void DoSomethingDele gate();
    >
    > protected static DoSomethingDele gate DoSomethingFunc ;
    >
    > protected static string SomeString = "N/A";
    >
    > public static void DoSomething()
    > {
    > Console.WriteLi ne("MyBase.DoSo mething()");
    > DoSomethingFunc ();
    > }
    > }
    >
    > public class MyChildClass : MyBaseClass
    > {
    > static MyChildClass()
    > {
    > Console.WriteLi ne("static MyChildClass()" );
    > DoSomethingFunc =
    > new DoSomethingDele gate(DoSomethin gImpl);
    > }
    >
    > protected static void DoSomethingImpl ()
    > {
    > Console.WriteLi ne("DoSomething ()");
    > }
    >
    > public static string TheString
    > {
    > get{return SomeString;}
    > set{SomeString = value;}
    > }
    >
    > }
    > }
    >[/color]


    Comment

    • Sunny

      #3
      Re: BUG in static constructors?!? !?

      Hi Richard,
      Thanks for posting. Please read inline.

      In article <ODccjpXoDHA.17 24@TK2MSFTNGP10 .phx.gbl>,
      chadich@yumspam yumYahoo.com says...[color=blue]
      > DoSomething() is a member of MyBaseClass, even though C# allows you to
      > access it via MyChildClass. Therefore no member of MyChildClass is
      > referenced. I actually like this behaviour, because it gives you more
      > granular control over static constructor execution for 'lazy' construction
      > of singletons etc. What I'm not certain I like is C# giving you access to a
      > public static member of a base type, when it removes all reference to the
      > type your are specifying in the IL (I looked and MyBaseClass gets called in
      > the IL, so it's definately C# doing this). I'll have to look up where this
      > behaviour is specified, as maybe there's a clue as to why it's this way.[/color]

      I'm still confused, as the MyBase is abstract, I.e. it purpose is
      exactly to be used as base, not directly. But I have checked, you can
      invoke a static member of abstract class?!? Yes, its written, that you
      can not create an object of that class, and nothing about static
      members, but still a little bit messy IMHO. I'm not surprised that in IL
      there is reference to MyBaseClass.Sta ticMember, as in spec is written,
      that there is exactly one storage location. No matter how many instances
      of a class are created, there is only ever one copy of a static field.
      But this still does not mean that that member is not member of the child
      class.
      Or I'm wrong?

      And my understanding is (uhh, was :) ) that inheritance is that, the new
      class just contains the base one, or at least acts like this. In the
      spec (10.2.1) explicitly is written:
      "A class inherits the members of its direct base class. Inheritance
      means that a class implicitly contains all members of its direct base
      class".
      If there was written, something like refers, not contains, I could
      accept that these members are not part of the child class.

      I'm not against the behaviour, I was just surprised that this do not
      correspond to the specs, or maybe the spec is not clear, or ... who
      knows ...

      Actually, if MS confirms that this is exactly what they had in mind, it
      should be stated more clearly.

      [color=blue]
      >
      > But anyway, keep in mind there are other constructs in which you can refer
      > to MyChildClass that don't result in the static constructor being fired, as
      > well, i.e. typeof(MyChildC lass), so I ultimately I think it's fair that base
      > class members should not cause the constructor to fire.[/color]

      About typeof(), when you invoke it, still there is no reference to any
      member of the class, so I also would not expect static constructor to be
      fired.
      [color=blue]
      >
      > Richard
      >[/color]


      Anyway, do you have any idea how to accomplish such a behavior.
      My goal is to create a base class for logging, which I can use in all my
      ..Net apps - webservices, winforms, console apps, etc. I need to invoke
      the logging function from everywhere, so static is the way :)
      I have created a custom Attribute class, and in the DoSomething() I
      check if the calling method is marked as a method which can (have to) be
      logged, so I can put this attribute only to methods which I'm currently
      interested in.

      As the method which will actually write the message in the log, will be
      different for every app, I wanted only to recreate that method, while
      all other checks before that to be implemented in the base. I can not
      make that method abstract, as I want it to be static, and there is no
      way to use static abstract :(

      I just tried that approach, assuming that static constructor will be
      invoked to hook the method.

      Any clue? I just want to place wherever I want MyChild.DoSomet hing(),
      and actually to use the DoSomethingFunc () only if some checks (for
      attribute, etc) are true in DoSomething.

      Thanks again for reading this.
      Sunny

      Comment

      • Richard A. Lowe

        #4
        Re: BUG in static constructors?!? !?

        > But this still does not mean that that member is not member of the child[color=blue]
        > class.
        > Or I'm wrong?[/color]

        This is why I was a bit surprised that the child class exposed the base
        member - since it seems to imply that it works the same way as an instance
        member (an instance member in MyBaseClass, whether virtual or not, will
        cause the static constructor of MyChildClass to fire if called).
        [color=blue]
        > Actually, if MS confirms that this is exactly what they had in mind, it
        > should be stated more clearly.[/color]

        Yes, I agree, it's a somewhat ambiguous, IMO.

        Richard

        --
        Veuillez m'excuser, mon Français est très pauvre. Cependant, si vous voyez
        mauvais C #, c'est mon défaut!
        "Sunny" <sunnyask@icebe rgwireless.com> wrote in message
        news:MPG.1a0f30 873e44923998969 b@msnews.micros oft.com...[color=blue]
        > Hi Richard,
        > Thanks for posting. Please read inline.
        >
        > In article <ODccjpXoDHA.17 24@TK2MSFTNGP10 .phx.gbl>,
        > chadich@yumspam yumYahoo.com says...[color=green]
        > > DoSomething() is a member of MyBaseClass, even though C# allows you to
        > > access it via MyChildClass. Therefore no member of MyChildClass is
        > > referenced. I actually like this behaviour, because it gives you more
        > > granular control over static constructor execution for 'lazy'[/color][/color]
        construction[color=blue][color=green]
        > > of singletons etc. What I'm not certain I like is C# giving you access[/color][/color]
        to a[color=blue][color=green]
        > > public static member of a base type, when it removes all reference to[/color][/color]
        the[color=blue][color=green]
        > > type your are specifying in the IL (I looked and MyBaseClass gets called[/color][/color]
        in[color=blue][color=green]
        > > the IL, so it's definately C# doing this). I'll have to look up where[/color][/color]
        this[color=blue][color=green]
        > > behaviour is specified, as maybe there's a clue as to why it's this way.[/color]
        >
        > I'm still confused, as the MyBase is abstract, I.e. it purpose is
        > exactly to be used as base, not directly. But I have checked, you can
        > invoke a static member of abstract class?!? Yes, its written, that you
        > can not create an object of that class, and nothing about static
        > members, but still a little bit messy IMHO. I'm not surprised that in IL
        > there is reference to MyBaseClass.Sta ticMember, as in spec is written,
        > that there is exactly one storage location. No matter how many instances
        > of a class are created, there is only ever one copy of a static field.
        > But this still does not mean that that member is not member of the child
        > class.
        > Or I'm wrong?
        >
        > And my understanding is (uhh, was :) ) that inheritance is that, the new
        > class just contains the base one, or at least acts like this. In the
        > spec (10.2.1) explicitly is written:
        > "A class inherits the members of its direct base class. Inheritance
        > means that a class implicitly contains all members of its direct base
        > class".
        > If there was written, something like refers, not contains, I could
        > accept that these members are not part of the child class.
        >
        > I'm not against the behaviour, I was just surprised that this do not
        > correspond to the specs, or maybe the spec is not clear, or ... who
        > knows ...
        >
        > Actually, if MS confirms that this is exactly what they had in mind, it
        > should be stated more clearly.
        >
        >[color=green]
        > >
        > > But anyway, keep in mind there are other constructs in which you can[/color][/color]
        refer[color=blue][color=green]
        > > to MyChildClass that don't result in the static constructor being fired,[/color][/color]
        as[color=blue][color=green]
        > > well, i.e. typeof(MyChildC lass), so I ultimately I think it's fair that[/color][/color]
        base[color=blue][color=green]
        > > class members should not cause the constructor to fire.[/color]
        >
        > About typeof(), when you invoke it, still there is no reference to any
        > member of the class, so I also would not expect static constructor to be
        > fired.
        >[color=green]
        > >
        > > Richard
        > >[/color]
        >
        >
        > Anyway, do you have any idea how to accomplish such a behavior.
        > My goal is to create a base class for logging, which I can use in all my
        > .Net apps - webservices, winforms, console apps, etc. I need to invoke
        > the logging function from everywhere, so static is the way :)
        > I have created a custom Attribute class, and in the DoSomething() I
        > check if the calling method is marked as a method which can (have to) be
        > logged, so I can put this attribute only to methods which I'm currently
        > interested in.
        >
        > As the method which will actually write the message in the log, will be
        > different for every app, I wanted only to recreate that method, while
        > all other checks before that to be implemented in the base. I can not
        > make that method abstract, as I want it to be static, and there is no
        > way to use static abstract :(
        >
        > I just tried that approach, assuming that static constructor will be
        > invoked to hook the method.
        >
        > Any clue? I just want to place wherever I want MyChild.DoSomet hing(),
        > and actually to use the DoSomethingFunc () only if some checks (for
        > attribute, etc) are true in DoSomething.
        >
        > Thanks again for reading this.
        > Sunny[/color]


        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: BUG in static constructors?!? !?

          Sunny <sunnyask@icebe rgwireless.com> wrote:[color=blue]
          > I'm still confused, as the MyBase is abstract, I.e. it purpose is
          > exactly to be used as base, not directly. But I have checked, you can
          > invoke a static member of abstract class?!? [/color]

          Absolutely - why would you not be able to?
          [color=blue]
          > Yes, its written, that you
          > can not create an object of that class, and nothing about static
          > members, but still a little bit messy IMHO.[/color]

          Why? One of the common patterns in OO is to have a publicly available
          abstract class which provides a factory method to return an instance of
          a derived class which the caller may not know about directly. Look at
          Encoding.GetEnc oding as an example of that.
          [color=blue]
          > I'm not surprised that in IL
          > there is reference to MyBaseClass.Sta ticMember, as in spec is written,
          > that there is exactly one storage location. No matter how many instances
          > of a class are created, there is only ever one copy of a static field.
          > But this still does not mean that that member is not member of the child
          > class.
          > Or I'm wrong?[/color]

          The spec isn't terribly clear on this. According to 17.2.5 (I'm using
          ECMA numbering, btw) "When a static member is referenced in a member-
          access (§14.5.4) of the form E.M, E must denote a type that has a
          member M." which would imply that the static method *was* a member of
          the derived class.
          [color=blue]
          > And my understanding is (uhh, was :) ) that inheritance is that, the new
          > class just contains the base one, or at least acts like this. In the
          > spec (10.2.1) explicitly is written:
          > "A class inherits the members of its direct base class. Inheritance
          > means that a class implicitly contains all members of its direct base
          > class".
          > If there was written, something like refers, not contains, I could
          > accept that these members are not part of the child class.
          >
          > I'm not against the behaviour, I was just surprised that this do not
          > correspond to the specs, or maybe the spec is not clear, or ... who
          > knows ...[/color]

          The specs are indeed unclear, unfortunately. I'm pretty sure the
          behaviour exhibited is the intended one, but it's not very clearly
          stated as far as I can see.
          [color=blue]
          > Anyway, do you have any idea how to accomplish such a behavior.
          > My goal is to create a base class for logging, which I can use in all my
          > .Net apps - webservices, winforms, console apps, etc. I need to invoke
          > the logging function from everywhere, so static is the way :)
          > I have created a custom Attribute class, and in the DoSomething() I
          > check if the calling method is marked as a method which can (have to) be
          > logged, so I can put this attribute only to methods which I'm currently
          > interested in.
          >
          > As the method which will actually write the message in the log, will be
          > different for every app, I wanted only to recreate that method, while
          > all other checks before that to be implemented in the base. I can not
          > make that method abstract, as I want it to be static, and there is no
          > way to use static abstract :(
          >
          > I just tried that approach, assuming that static constructor will be
          > invoked to hook the method.
          >
          > Any clue? I just want to place wherever I want MyChild.DoSomet hing(),
          > and actually to use the DoSomethingFunc () only if some checks (for
          > attribute, etc) are true in DoSomething.[/color]

          To be honest, I'm still not sure about where the derived class comes in
          - surely as soon as you have more than one of those derived classes,
          things come unstuck anyway, don't they, as you'd be resetting
          DoSomethingFunc .

          I've a feeling the singleton pattern *may* be useful to you, but
          without understanding your problem better it's hard to say for sure.

          --
          Jon Skeet - <skeet@pobox.co m>
          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

          If replying to the group, please do not mail me too

          Comment

          • Sunny

            #6
            Re: BUG in static constructors?!? !?

            Hi Jon, thanks for posting.
            Pls, read inline
            [color=blue]
            > Why? One of the common patterns in OO is to have a publicly available
            > abstract class which provides a factory method to return an instance of
            > a derived class which the caller may not know about directly. Look at
            > Encoding.GetEnc oding as an example of that.[/color]
            It seems I have missed something in my education (as usual :) ). May you
            give some examples of implementation, or starting point?
            [color=blue]
            > The spec isn't terribly clear on this. According to 17.2.5 (I'm using
            > ECMA numbering, btw) "When a static member is referenced in a member-
            > access (§14.5.4) of the form E.M, E must denote a type that has a
            > member M." which would imply that the static method *was* a member of
            > the derived class.[/color]
            And, if it IS a member of the derived class, why the ctor is not fired?
            [color=blue]
            > The specs are indeed unclear, unfortunately. I'm pretty sure the
            > behaviour exhibited is the intended one, but it's not very clearly
            > stated as far as I can see.[/color]
            Am I missing something in the theory and practice of OO, which should
            explain why this have to be intended?
            [color=blue]
            > To be honest, I'm still not sure about where the derived class comes in
            > - surely as soon as you have more than one of those derived classes,
            > things come unstuck anyway, don't they, as you'd be resetting
            > DoSomethingFunc .[/color]
            Yes, you are right, but I can not think about anything else.[color=blue]
            >
            > I've a feeling the singleton pattern *may* be useful to you, but
            > without understanding your problem better it's hard to say for sure.[/color]

            This is only for internal use, I want to have the same (or :) mostly the
            same) log mechanism in all my apps, and to rewrite only the way actual
            log is stored.
            So it seems that there can be 2 ways from that point - singleton pattern
            (I have to read :) ), or not to use static ctor, but any static method
            which will attach the delegate.

            Thanks again for the posting
            Sunny

            Comment

            • Jon Skeet [C# MVP]

              #7
              Re: BUG in static constructors?!? !?

              Sunny <sunnyask@icebe rgwireless.com> wrote:[color=blue][color=green]
              > > Why? One of the common patterns in OO is to have a publicly available
              > > abstract class which provides a factory method to return an instance of
              > > a derived class which the caller may not know about directly. Look at
              > > Encoding.GetEnc oding as an example of that.[/color][/color]
              [color=blue]
              > It seems I have missed something in my education (as usual :) ). May you
              > give some examples of implementation, or starting point?[/color]

              Okay, very simple implementation example for WebRequest. I'm not saying
              this is what *actually* happens, but it might be close:

              public WebRequest Create (string uri)
              {
              if (uri.StartsWith ("http:"))
              return new HttpWebRequest (uri);
              if (uri.StartsWith ("ftp:"))
              return new FtpWebRequest (ur);
              ...
              }

              It means the client doesn't need to know about the derived classes
              directly.
              [color=blue][color=green]
              > > The spec isn't terribly clear on this. According to 17.2.5 (I'm using
              > > ECMA numbering, btw) "When a static member is referenced in a member-
              > > access (§14.5.4) of the form E.M, E must denote a type that has a
              > > member M." which would imply that the static method *was* a member of
              > > the derived class.[/color][/color]
              [color=blue]
              > And, if it IS a member of the derived class, why the ctor is not fired?[/color]

              Well that's the trick - it's really only "sort of" a member itself; as
              we've seen, the compiled code has no mention of the base class.
              [color=blue][color=green]
              > > The specs are indeed unclear, unfortunately. I'm pretty sure the
              > > behaviour exhibited is the intended one, but it's not very clearly
              > > stated as far as I can see.[/color][/color]
              [color=blue]
              > Am I missing something in the theory and practice of OO, which should
              > explain why this have to be intended?[/color]

              Well, you're actually calling the base method, and as it's a static
              method there's no possibility of it being overridden, so no polymorphic
              behaviour is needed. As far as everything apart from class
              initialisation might be concerned, it is exactly the same as calling
              the base class's method - so that's what it gets turned into,
              unfortunately for you.
              [color=blue][color=green]
              > > To be honest, I'm still not sure about where the derived class comes in
              > > - surely as soon as you have more than one of those derived classes,
              > > things come unstuck anyway, don't they, as you'd be resetting
              > > DoSomethingFunc .[/color][/color]
              [color=blue]
              > Yes, you are right, but I can not think about anything else.[/color]
              [color=blue][color=green]
              > > I've a feeling the singleton pattern *may* be useful to you, but
              > > without understanding your problem better it's hard to say for sure.[/color]
              >
              > This is only for internal use, I want to have the same (or :) mostly the
              > same) log mechanism in all my apps, and to rewrite only the way actual
              > log is stored.
              > So it seems that there can be 2 ways from that point - singleton pattern
              > (I have to read :) ), or not to use static ctor, but any static method
              > which will attach the delegate.[/color]

              Here's some info about singletons which you might find useful:

              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.


              --
              Jon Skeet - <skeet@pobox.co m>
              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

              If replying to the group, please do not mail me too

              Comment

              • Sunny

                #8
                Re: BUG in static constructors?!? !?

                Thanks Jon,
                very usefull.

                Sunny

                Comment

                Working...