473,473 Members | 2,100 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Generics: force type initialiser of T

Given a generic method "of T", is there a good way of ensuring that any
static ctor on T has executed? Following code demonstrates (TestClass1)
that via generics you can use the Type instance long before the static
ctor fires.

With a generic class and the "new()" clause, I can force this in the
static ctor of the generic class, but this is not always convenient,
plus may (possibly?) be seen as a no-op [not sure here].

Sample; ideally I'd get "Static ctor 1" to output before the type-name
of 1 (as per the second test), without using any hacks...

Marc

using System;
class Prog {
static void Main() {
GenMethod<TestClass1>();
GenClass<TestClass2>.Method();
}
static void GenMethod<T>() {
Console.WriteLine("GenMethod" + typeof(T).FullName);
}
}
class GenClass<Twhere T : new()
{
static GenClass() { // possibly set noinlining
new T(); // throw away; forces T's static ctor
}
public static void Method() {
Console.WriteLine("Method: " + typeof(T).FullName);
}
}
class TestClass1 {
static TestClass1() {
Console.WriteLine("Static ctor 1");
}
}
class TestClass2 {
static TestClass2() {
Console.WriteLine("Static ctor 2");
}
}

Dec 4 '06 #1
10 2214
Given a generic method "of T", is there a good way of ensuring that
any static ctor on T has executed? Following code demonstrates
(TestClass1) that via generics you can use the Type instance long
before the static ctor fires.

With a generic class and the "new()" clause, I can force this in the
static ctor of the generic class, but this is not always convenient,
plus may (possibly?) be seen as a no-op [not sure here].

Sample; ideally I'd get "Static ctor 1" to output before the type-name
of 1 (as per the second test), without using any hacks...
Hmmm... I haven't found a way to do this. You can't use reflection to do
this because invoking a type initializer is disallowed. For example, this
fails:

static GenClass()
{
ConstructorInfo staticConstructor = typeof(T).GetConstructor(BindingFlags.Static
| BindingFlags.NonPublic, null, Type.EmptyTypes, null);
staticConstructor.Invoke(null);
}

However, the type initializers is guaranteed to be when the type is accessed
in such a way that initialization is required. So, you could have a dummy
static method that is called via reflection:

using System;
using System.Reflection;

class Program
{
static void Main()
{
GenMethod<TestClass1>();
GenClass<TestClass2>.Method();
}
static void GenMethod<T>()
{
Console.WriteLine("GenMethod" + typeof(T).FullName);
}
}
class GenClass<Twhere T: new()
{
static GenClass()
{
MethodInfo dummyMethod = typeof(T).GetMethod("DummyMethod", BindingFlags.Static
| BindingFlags.NonPublic, null, Type.EmptyTypes, null);
dummyMethod.Invoke(null, null);
}
public static void Method()
{
Console.WriteLine("Method: " + typeof(T).FullName);
}
}
class TestClass1
{
static void DummyMethod() { }
static TestClass1()
{
Console.WriteLine("Static ctor 1");
}
}
class TestClass2
{
static void DummyMethod() { }
static TestClass2()
{
Console.WriteLine("Static ctor 2");
}
}

My big question is, why do you want to do this? If you're trying to get type
initializers to be called in some sort of deterministic way, it might be
an indication that you need a different design.

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 4 '06 #2
That is more or less where I got to... I'll avoid the reflection,
though - seems a bit scrappy : but thanks all the same.

The why is complex, and relates to registering a few interfaces with a
lookup (dictionary mapping interfaces to instances implementing that
interface), for use e.g. by some generic lazy-loading, where the "thing
doing the loading" (i.e. an uninitialised collection of orders) knows
how to get its data in terms of interfaces (providers / adapters for
want of a better term), but doesn't know who (which specific class)
will be providing the data. Until I applied the "new()" bit, in a few
test cases no class was registering itself as the provider in time for
the lazy lookup, so it was failing (gracefully).

With the fix, things are correctly saying "hey, I exist and can do
<x>"...

The main objective is to do lazy loading where it doesn't care if it
has direct (SqlClient) or indirect (WSDL etc) access to the data - as
long as the concrete class meets the interface correctly.

Of course, if you care to cite a pattern to look at?

Marc

Dec 4 '06 #3
I know this is kinda hokey, but:

class TestClass2 {
public static bool Initialized=false;
static TestClass2() {
Initialized=true;
Console.WriteLine("Static ctor 2");
}
}

I wonder if that would be usable...

Peter

--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com


"Marc Gravell" wrote:
Given a generic method "of T", is there a good way of ensuring that any
static ctor on T has executed? Following code demonstrates (TestClass1)
that via generics you can use the Type instance long before the static
ctor fires.

With a generic class and the "new()" clause, I can force this in the
static ctor of the generic class, but this is not always convenient,
plus may (possibly?) be seen as a no-op [not sure here].

Sample; ideally I'd get "Static ctor 1" to output before the type-name
of 1 (as per the second test), without using any hacks...

Marc

using System;
class Prog {
static void Main() {
GenMethod<TestClass1>();
GenClass<TestClass2>.Method();
}
static void GenMethod<T>() {
Console.WriteLine("GenMethod" + typeof(T).FullName);
}
}
class GenClass<Twhere T : new()
{
static GenClass() { // possibly set noinlining
new T(); // throw away; forces T's static ctor
}
public static void Method() {
Console.WriteLine("Method: " + typeof(T).FullName);
}
}
class TestClass1 {
static TestClass1() {
Console.WriteLine("Static ctor 1");
}
}
class TestClass2 {
static TestClass2() {
Console.WriteLine("Static ctor 2");
}
}

Dec 4 '06 #4

Marc Gravell wrote:
That is more or less where I got to... I'll avoid the reflection,
though - seems a bit scrappy : but thanks all the same.

The why is complex, and relates to registering a few interfaces with a
lookup (dictionary mapping interfaces to instances implementing that
interface), for use e.g. by some generic lazy-loading, where the "thing
doing the loading" (i.e. an uninitialised collection of orders) knows
how to get its data in terms of interfaces (providers / adapters for
want of a better term), but doesn't know who (which specific class)
will be providing the data. Until I applied the "new()" bit, in a few
test cases no class was registering itself as the provider in time for
the lazy lookup, so it was failing (gracefully).

With the fix, things are correctly saying "hey, I exist and can do
<x>"...
Perhaps I'm being too traditional with this approach, but I would solve
this problem by taking it out "from under the covers" as it were. If
the problem is to register a bunch of classes against some interfaces
and thus to achieve some sort of dynamic loading scenario ("I loaded
this assembly and now I can do these things....") then perhaps this is
something to do explicitly in code, rather than trying to make it
happen "magically" under the covers.

In brief, perhaps you've outsmarted yourself. I do it all the time. :-)

Let's say that you want to load an assembly and then register all of
the classes in it with your dictionary, so that you know which
interfaces have implementations in that assembly, and which classes
correspond to which interfaces. I would put a sealed class called
"RegisterCapabilities" (or something equally illuminating) into the
assembly, and give it one static method, something like "Register". The
Register method would register all of the classes in the assembly with
the dictionary, either by doing so explicitly (my personal choice) or
by calling each class and asking it to register itself.

Then, when your application loads an assembly, it should call
RegisterCapabilities.Register() as its first act. If the assembly
doesn't contain that class and static method, then it's malformed and
can't be used.

If you're not dynamically loading the assembly, then your main program
can do this as the first thing it does, since the correct routine to
call is already known.

Since the registration is now explicit in code, you can easily ensure
that it's happening at the right place without any jiggery-pokery in
static initializers. I think that this solution would also be easier to
maintain: the code is explicit and it's easy to see what it does (and
easy to debug if it fails).

As I said: perhaps that solution is too clunky. I tend to prefer things
out where I can see them... every time I've experimented with clever,
under-the-covers, "magic" solutions to problems, those solutions have
come back to bite me.... :-)

Dec 4 '06 #5
No - I think you are right; me outsmarting myself... this is more or
less what I currently have in my "Main()" and my "global.asax"
respectively (give or take some abstraction to some wrapper methods).

The new() trick was helpful in a scenario where the provider (in this
case) actually just wrapped functionality from other services, so the
provider itself could be safely abstracted down to the lower layers...
but by the same token, there is no harm in registering it explicitely
in the upper layers, or just calling a Register() method.

But I think you pretty much hit what I was concluding myeslf... just
about doable, but why make life tricky for myself ;-p

Cheers for input,

Marc

Dec 4 '06 #6
In the static case, yes, but I was referring to the generic case where
the concrete type (TestClass2) is not explicitely known (except as "T")
at dll-compile-time (the "T" being provided by a referencing assembly).
Of course, if C# supported static interfaces we might be able to do
something.

But I think I'm sorted; cheers for the input,

Marc

Dec 4 '06 #7
On 4 Dec 2006 08:47:16 -0800, "Marc Gravell" <ma**********@gmail.com>
wrote:
>Given a generic method "of T", is there a good way of ensuring that any
static ctor on T has executed? Following code demonstrates (TestClass1)
that via generics you can use the Type instance long before the static
ctor fires.
You're barking up the wrong tree. There's nothing different between
generics and non-generics regarding the execution of static ctors.

The actual issue demonstrated by your sample code is the fact that
TYPE REFLECTION (via typeof) does not trigger the static ctor. To my
knowledge, it was never supposed to do that.

As an illustration, insert the following method call at the first line
of your Main method:

Console.WriteLine(typeof(TestClass1).FullName);

You will notice that even with this NON-GENERIC call, the static ctor
of TestClass1 does not execute. That's because you're merely doing
reflection. Generics have nothing to do with it.
--
http://www.kynosarges.de
Dec 5 '06 #8
With all due respect, I know full well which trees I am barking at.

I didn't suggest that looking at the Type object does (or should) trigger
the static ctor executior; I merely asked whether it was possible to force
the type initialiser to run (if it hasn't already), specifically in the case
where the type in question was a generic.

Generics has *everything* to do with it. If it wasn't for generics, I could
simply call a ForceInit() (no-op) static method to force the static ctor to
load.

Marc
Dec 5 '06 #9
In that case I'm sorry for the misunderstanding.

In your original code example, the static ctor was not executed
because the only type access was via typeof() calls. So I mistakenly
assumed your goal was to execute static ctors before typeof() calls.

Your last paragraph in this post states your real question much more
succinctly, and I see that all relevant things have already been said.
On Tue, 5 Dec 2006 08:53:58 -0000, "Marc Gravell"
<ma**********@gmail.comwrote:
>With all due respect, I know full well which trees I am barking at.

I didn't suggest that looking at the Type object does (or should) trigger
the static ctor executior; I merely asked whether it was possible to force
the type initialiser to run (if it hasn't already), specifically in the case
where the type in question was a generic.

Generics has *everything* to do with it. If it wasn't for generics, I could
simply call a ForceInit() (no-op) static method to force the static ctor to
load.

Marc
--
http://www.kynosarges.de
Dec 5 '06 #10
No - I think you are right; me outsmarting myself...

:-) Occasionally, I'll be working on a design and run into some sort of snare.
Then, when coming back to the design (after spending some time away), I'll
discover that I was just trying to be too clever.

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 5 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: Anders Borum | last post by:
Hello! Now that generics are introduces with the next version of C#, I was wondering what kind of performance gains we're going to see, when switching from e.g. the general hashtable to a...
4
by: Gazarsgo | last post by:
This seems to be a bit of a contradiction, but how can I construct a Generic class using a System.Type variable that is assigned at run time? Is there some parallel to the Generics concept that...
11
by: herpers | last post by:
Hello, I probably don't see the obvious, but maybe you can help me out of this mess. The following is my problem: I created two classes NormDistribution and DiscDistribution. Both classes...
1
by: Vladimir Shiryaev | last post by:
Hello! Exception handling in generics seems to be a bit inconsistent to me. Imagine, I have "MyOwnException" class derived from "ApplicationException". I also have two classes...
4
by: Cedric Rogers | last post by:
I wasn't sure if I could do this. I believe I am stretching the capability of what generics can do for me but here goes. I have a generic delegate defined as public delegate bool...
13
by: rkausch | last post by:
Hello everyone, I'm writing because I'm frustrated with the implementation of C#'s generics, and need a workaround. I come from a Java background, and am currently writing a portion of an...
4
by: Random | last post by:
I want to define a generics method so the user can determine what type they expect returned from the method. By examining the generics argument, I would determine the operation that needs to be...
7
by: groups | last post by:
This is my first foray into writing a generic method and maybe I've bitten off more than I can chew. My intent is to have a generic method that accepts a value name and that value will be...
10
by: Udi | last post by:
Hi All, Two questions regarding Generics: 1. I'd like to constrain my Type parameter to be one of a preefined group of types. For example: class Field<Twhere T: Byte, Int, String,...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.