Override static derived variable

K

knocte

Hello.

I have a problem with C# language. I want to define an algorithm on a
static function inside an abstract class. This function calls a static
variable inside the same class. Then I want to define some derived
classes wich inherit the function and override the variable, but it
doesn't work.

Testcase:

using System;

namespace Test
{

abstract public class X {
protected static string var = "x";

public static void print_my_var(){
Console.WriteLine("my var is " + var);
}
}

public class A : X {
protected static new string var = "a";
}

public class B : X
{
protected static new string var = "b";
}

class ClassTest {

[STAThread]
static void Main(string[] args)
{
X.print_my_var();
A.print_my_var();
B.print_my_var();
}
}
}


result:
my var is x
my var is x
my var is x

expected results:
my var is x
my var is a
my var is b

How can obtain the expected results using static methods and static
variables and without creating the static method A or B?

Thanks in advance.

Andrew

--
 
J

Joanna Carter \(TeamB\)

I have a problem with C# language. I want to define an algorithm on a
static function inside an abstract class. This function calls a static
variable inside the same class. Then I want to define some derived
classes wich inherit the function and override the variable, but it
doesn't work.

I would have said that you should not override the variable, just the
initialising code in a static constructor.

abstract public class X
{
protected static string var;

protected static SetVar(string value)
{
var = value;
}

static X()
{
SetVar("X");
}

public static void print_my_var()
{
Console.WriteLine("my var is " + var);
}
}

public class A : X
{
static A()
{
SetVar("A");
}

But this doesn't work either as it appears that the only static constructor
to be called in class A is X().

I must admit that this is not as I would have expected. Does anyone know if
this is a bug in beta 1 ?

Joanna
 
C

Chad Z. Hower aka Kudzu

knocte said:
I have a problem with C# language. I want to define an algorithm on a
static function inside an abstract class. This function calls a static
variable inside the same class. Then I want to define some derived
classes wich inherit the function and override the variable, but it
doesn't work.

You cannnot override statics in C#, or in fact in .NET. In Delphi.NET you can, but they are done using
some magic to preserve compatibilty and dont export as normal statics for other languages.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Get your ASP.NET in gear with IntraWeb!
http://www.atozed.com/IntraWeb/
 
C

Chad Z. Hower aka Kudzu

Joanna Carter \(TeamB\) said:
But this doesn't work either as it appears that the only static
constructor to be called in class A is X().

I must admit that this is not as I would have expected. Does anyone
know if this is a bug in beta 1 ?

What code are you using to instantiate them? Statics in .NET are not at all like in Delphi, and Im
constantly hitting roadblocks here. I understand why they did it the way they did, and it has some
advantages but its requires some royal work arounds sometimes.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Make your ASP.NET applications run faster
http://www.atozed.com/IntraWeb/
 
J

Joanna Carter \(TeamB\)

What code are you using to instantiate them? Statics in .NET are not at all like in Delphi,
and Im constantly hitting roadblocks here. I understand why they did it the way they did,
and it has some advantages but its requires some royal work arounds
sometimes.

Hi Chad

I am not instantiating them for this example, I am just using static calls
as demonstrated by the OP.

Console.WriteLine(Thing.GetVar());
Console.WriteLine(Derived.GetVar());

Both return "Thing", the Derived static constructor doesn't get called at
all if there is a static constructor on the base class. This seems wierd; I
wasn't expecting virtual/override behaviour, just that the static
constructor on Derived would possibly hide that of Thing, but definitely
that it would get executed.

Can an MVP or someone from MS please confirm that this behaviour is
intentional ?

Joanna (Another frustrated Delphi OO expert)
 
J

Jon Skeet [C# MVP]

Joanna Carter (TeamB) said:
I am not instantiating them for this example, I am just using static calls
as demonstrated by the OP.

Console.WriteLine(Thing.GetVar());
Console.WriteLine(Derived.GetVar());

Those both compile to the same thing - there will be nothing which
actually references Derived.GetVar in the IL, as there is really no
such method. Therefore there is (as far as the CLR is concerned) no
need to initialise the Derived class.
 
C

Chad Z. Hower aka Kudzu

Jon Skeet said:
Those both compile to the same thing - there will be nothing which
actually references Derived.GetVar in the IL, as there is really no
such method. Therefore there is (as far as the CLR is concerned) no
need to initialise the Derived class.

Joanna,

I'll add a bit to Jon's reply since I know you have a Delphi background.

..NET does NOT load a class until it is ACTUALLY used. So the static constructor for a given class
will not be called, until the class is actually needed. All classes are load on demand, vs
Delphi where the units get their initialization sections called on start up of the application.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Develop ASP.NET applications easier and in less time:
http://www.atozed.com/IntraWeb/
 
J

Joanna Carter \(TeamB\)

I'll add a bit to Jon's reply since I know you have a Delphi background.

.NET does NOT load a class until it is ACTUALLY used. So the static constructor for
a given class will not be called, until the class is actually needed. All classes are load
on demand, vs Delphi where the units get their initialization sections called on start up
of the application.

Unfortunately, I now understand that bit :-(

But the good news is that I have solved the OP's problem. All you have to do
is to re-declare the GetVar() static method and call the base method !!

class Thing
{
private static string var;

protected static void SetVar(string value)
{
var = value;
}

static Thing()
{
SetVar("Thing");
}

public static string GetVar()
{
return var;
}
}

class Derived : Thing
{
static Derived()
{
SetVar("Derived");
}

public static new string GetVar()
{
return Thing.GetVar();
}
}

Yeeesss !!!

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 
J

Jon Skeet [C# MVP]

Chad Z. Hower aka Kudzu said:
I'll add a bit to Jon's reply since I know you have a Delphi background.

.NET does NOT load a class until it is ACTUALLY used. So the static
constructor for a given class will not be called, until the class is
actually needed. All classes are load on demand, vs Delphi where the
units get their initialization sections called on start up of the
application.

There's a slight twist here due to the beforefieldinit flag, which is
present on all classes compiled by the C# compiler which don't have a
static constructor. Those classes are "lazily" initialized, which means
they're initialized at some point before the first static field access
- it actually usually means they're eagerly initialized at the start of
the first method which *might* use the type.

See http://www.pobox.com/~skeet/csharp/beforefieldinit.html
 
M

Michael S

Chad Z. Hower aka Kudzu said:
Joanna,

I'll add a bit to Jon's reply since I know you have a Delphi background.

.NET does NOT load a class until it is ACTUALLY used. So the static
constructor for a given class
will not be called, until the class is actually needed. All classes are
load on demand, vs
Delphi where the units get their initialization sections called on start
up of the application.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Develop ASP.NET applications easier and in less time:
http://www.atozed.com/IntraWeb/

I'll add a bit as well as I have followed both Delphi and C# from scratch
and have some issues.
I think the Pascal way of doing things with having units as a concrete
subject in the system a neat thing.
This is why Delphi can sport static variables while the concept is not
present in the pascal language per se.

The Delphi way of having a type of object is extremely useful. Having a
concept of self (this) for a class (static) function is great. This
construct also gives room for classhelpers, why I love Delphi.NET when
building general- or util-classes.

The C# view that a class cannot be aware of self and not participate in
polymorphism is a contrieved construct. Delphi proves C# wrong. This is one
of the most irritating things about C#. Not to mention how C# handles
indexers. Yet again Delphi proves how things should, could and does work.

My bet is that C# 3.0 will sport both class types and class helpers. And
VB-style indexers, even though it's a Delphi-thing.

Joanna: You just can't code Delphi in C#. But you could always build some of
your classes in Delphi.NET

- Michael S
 
C

Chad Z. Hower aka Kudzu

Michael S said:
I think the Pascal way of doing things with having units as a concrete
subject in the system a neat thing.

At first this seemed better, but really the .NET way is better here. You can better split your
classes up into files without altering their visibility in namespaces.
This is why Delphi can sport static variables while the concept is not
present in the pascal language per se.

In your context what do you mean by static variables? Are you referring to globals?
The Delphi way of having a type of object is extremely useful. Having

This is one area that Delphi did better IMO. .NET took it much farther and overall there is more
there, but the basic idea of a Type is a lot easier to work with and more useful in Delphi.
a concept of self (this) for a class (static) function is great. This
construct also gives room for classhelpers, why I love Delphi.NET when
building general- or util-classes.

Yes, I sorely miss this functionality. However the reason .NET does not implement it is becuase
of how it treats types in the first place and the fact that there is not VMT in a type at all.

Delphi.NET works because they make some magic and some hidden .NET classes in the
background.
The C# view that a class cannot be aware of self and not participate
in polymorphism is a contrieved construct. Delphi proves C# wrong.

A constant sore spot that causes me grief.
This is one of the most irritating things about C#. Not to mention how
C# handles indexers. Yet again Delphi proves how things should, could
and does work.

What differences do you see here? I've not had issues with indexers in C# vs Delphi.
My bet is that C# 3.0 will sport both class types and class helpers.

When you say class helpers - you arent referring to the class helper feature added to
Delphi.NET are you? Thats highly domain specific and was only added to allow compatibility
with older Delphi code yet let newer code use FCL objects instead of VCL bases.
Joanna: You just can't code Delphi in C#. But you could always build
some of your classes in Delphi.NET

Except that a lot of the Delphi magic including the type functinoality does not export, or exports
with wierd interfaces and is for all intents and purposes not useable by non Delphi.NET
languages.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Develop ASP.NET applications easier and in less time:
http://www.atozed.com/IntraWeb/
 
M

Michael S

Chad Z. Hower aka Kudzu said:
At first this seemed better, but really the .NET way is better here. You
can better split your
classes up into files without altering their visibility in namespaces.

There is no such thing as a namespace when it comes to CIL. That's syntactic
sugar allowing classnames to contain dots.

In your context what do you mean by static variables? Are you referring to
globals?

I mean variables that are defined in the implementation section. Unit-scope.
This is one area that Delphi did better IMO. .NET took it much farther and
overall there is more
there, but the basic idea of a Type is a lot easier to work with and more
useful in Delphi.


Yes, I sorely miss this functionality. However the reason .NET does not
implement it is becuase
of how it treats types in the first place and the fact that there is not
VMT in a type at all.

No. That's not the reason.
Delphi.NET works because they make some magic and some hidden .NET classes
in the
background.

No. There is no magic. If it compiles to CIL it's ok.
A constant sore spot that causes me grief.

What differences do you see here? I've not had issues with indexers in C#
vs Delphi.

No? By having to build nested classes if you want more than one indexer.
Elegant, yes. Useful, no. Hate it? Yes.
When you say class helpers - you arent referring to the class helper
feature added to
Delphi.NET are you? Thats highly domain specific and was only added to
allow compatibility
with older Delphi code yet let newer code use FCL objects instead of VCL
bases.

Yes and no. Borland created classhelpers mostly for handling the
TObject.Free method. But it is a mighty thing they have created. Very
useful. Borland have created another dimension of OO. With Delphi.NET you
don't see util classes or functions. You can just expand a class. This is a
valueable feature of the pascal language not present in C#. I miss it.
Except that a lot of the Delphi magic including the type functinoality
does not export, or exports
with wierd interfaces and is for all intents and purposes not useable by
non Delphi.NET
languages.

So, we just do what we always do. Wrap great code in a lame proxy. For all
classes that needs to be public we need to be CLS-compliant. Nothing new
here.
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

- Michael S
 
C

Chad Z. Hower aka Kudzu

Michael S said:
There is no such thing as a namespace when it comes to CIL. That's
syntactic sugar allowing classnames to contain dots.

Not at the IL level, but at the code level which is what he was referring to. Its going to be
difficult not to mix terms because he's coming from Delphi and some words in Delphi are the
same but have different meaning. This makes some things very hard to "cross" discuss and very
difficult for non Delphites to catch.

When I talked about visibilty in namespaces, I was speaking of compile time. In C# you can move
a class to another unit without affecting any code. In Delphi you can if you have not fully
qualified it. Usually in Delphi you do not fully qualify, but when conflicts come up of
names its necessary. Delphi.NET improves this, but also keeps with backward compatibility.
I mean variables that are defined in the implementation section.
Unit-scope.

These are global variables. They are not statics per say. In Delphi.NET they are implemented by
"magic", Delphi exports a unit class per unit and makes them statics in that unit.
No. That's not the reason.

Yes it is - .NET classes are implemented very differently than Delphi classes were.
No. There is no magic. If it compiles to CIL it's ok.

As far as the other languages are concerned it is magic. Delphi takes and emits "foreign" objects
and performs "compiler magic" translations when resused with the Delphi language, class
helpers, virtual statics, globals, and more.
No? By having to build nested classes if you want more than one
indexer. Elegant, yes. Useful, no. Hate it? Yes.

You can have more than one indexer. You can declare:

this[string aValue]
and
this[int aValue]

in the same object.
Yes and no. Borland created classhelpers mostly for handling the
TObject.Free method. But it is a mighty thing they have created. Very

No way - no offense but you do not have an in depth understanding of what exactly the class
helpers and other parts of the Delphi.NET compiler does.

Class helpers are used to map TObject to System.Object, Component, and several others, YET
still add all the extra stuff that VCL had at that level. Its used for WAY more than just Free.
Its used to add Owner and dozens if not hundreds of other items.
useful. Borland have created another dimension of OO. With Delphi.NET
you don't see util classes or functions. You can just expand a class.
This is a valueable feature of the pascal language not present in C#.
I miss it.

Class helpers (even ask Danny) are a bit of a hack and ONLY usable from within Delphi. Load
Borland.VCL in C# and you wont see any of the items added by class helper to TComponent. Its
only visible when used in Delphi becuase Delphi implements a LOT of "magic" by interpreting
..NET structures it emits and handling them at the compiler level. These certainly are IL "legal"
but they are NOT recognized by ANY other CLS / CTS implementation.

Its a good solution for allowing Delphi to remain backward compatible - but it should NOT be
used moving forward in your own .NET code as you will not be able to export your libaries and be
usable by other .NET languages.

We have some of the largest and most compmlicated .NET assemblies in existence written in
Delphi.NET, in fact bigger than the VCL. Which ones? Well namely Indy and IntraWeb, both of
which ship as part of Delphi, so we've been through it all.




--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Get your ASP.NET in gear with IntraWeb!
http://www.atozed.com/IntraWeb/
 
K

knocte

Joanna Carter (TeamB) escribió:
Unfortunately, I now understand that bit :-(

But the good news is that I have solved the OP's problem. All you have to do
is to re-declare the GetVar() static method and call the base method !!

class Thing
{
private static string var;

protected static void SetVar(string value)
{
var = value;
}

static Thing()
{
SetVar("Thing");
}

public static string GetVar()
{
return var;
}
}

class Derived : Thing
{
static Derived()
{
SetVar("Derived");
}

public static new string GetVar()
{
return Thing.GetVar();
}
}

Yeeesss !!!

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker


Hello Joanna, thanks for your interest. Although the first concept I
wanted to make, is not allowed (as Kudzu says), I think this could be a
nice workaround (but I haven't tested it yet).

The problem is that, if I do it this way, I have to override the method
GetVar in every derived class. And this is one of the things I wanted to
avoid, so as to improve reusability.

Thanks very much.

Andrew

--
 

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

Top