BUG in static constructors?!?!?

S

Sunny

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.TheString = "Set";
MyChildClass.DoSomething();
Console.WriteLine("Press enter to continue");
Console.ReadLine();
}
}

public abstract class MyBaseClass
{
protected delegate void DoSomethingDelegate();

protected static DoSomethingDelegate DoSomethingFunc;

protected static string SomeString = "N/A";

public static void DoSomething()
{
Console.WriteLine("MyBase.DoSomething()");
DoSomethingFunc();
}
}

public class MyChildClass : MyBaseClass
{
static MyChildClass()
{
Console.WriteLine("static MyChildClass()");
DoSomethingFunc =
new DoSomethingDelegate(DoSomethingImpl);
}

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

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

}
}
 
R

Richard A. Lowe

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(MyChildClass), so I ultimately I think it's fair that base
class members should not cause the constructor to fire.

Richard
 
S

Sunny

Hi Richard,
Thanks for posting. Please read inline.

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.

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.StaticMember, 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.

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(MyChildClass), so I ultimately I think it's fair that base
class members should not cause the constructor to fire.

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.


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.DoSomething(),
and actually to use the DoSomethingFunc() only if some checks (for
attribute, etc) are true in DoSomething.

Thanks again for reading this.
Sunny
 
R

Richard A. Lowe

But this still does not mean that that member is not member of the child
class.
Or I'm wrong?

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).
Actually, if MS confirms that this is exactly what they had in mind, it
should be stated more clearly.

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

Richard
 
J

Jon Skeet [C# MVP]

Sunny said:
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?!?

Absolutely - why would you not be able to?
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.

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.GetEncoding as an example of that.
I'm not surprised that in IL
there is reference to MyBaseClass.StaticMember, 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?

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.
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 ...

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.
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.DoSomething(),
and actually to use the DoSomethingFunc() only if some checks (for
attribute, etc) are true in DoSomething.

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.
 
S

Sunny

Hi Jon, thanks for posting.
Pls, read inline
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.GetEncoding as an example of that.
It seems I have missed something in my education (as usual :) ). May you
give some examples of implementation, or starting point?
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.
And, if it IS a member of the derived class, why the ctor is not fired?
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.
Am I missing something in the theory and practice of OO, which should
explain why this have to be intended?
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.
Yes, you are right, but I can not think about anything else.
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.

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
 
J

Jon Skeet [C# MVP]

It seems I have missed something in my education (as usual :) ). May you
give some examples of implementation, or starting point?

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.
And, if it IS a member of the derived class, why the ctor is not fired?

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.
Am I missing something in the theory and practice of OO, which should
explain why this have to be intended?

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.
Yes, you are right, but I can not think about anything else.

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.

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

http://www.pobox.com/~skeet/csharp/singleton.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top