ASP.NET 2.0: static instance of reference type is not always set to null

V

Vagif Abilov

We have several Web projects where we suddenly began experiencing various
problems after porting them to .NET 2.0. I debugged one of them and here's
what I've found:

In one of referenced assemblies there was a class with static members of
other class:

class A
{
...
static B b;

void Init()
{
if(b != null)
{
b = new B();
}
}
}

The problem was related to "b" instance, so I ran a debugger session and
discovered that I never entered code "b = new B()". The member variable "b"
has always been instantiated when I checked its value in debug session!

Then I slightly modified the code:

class A
{
...
static B b = null;

void Init()
{
if(b != null)
{
b = new B();
}
}
}

Then everything worked. But why? If we have a reference type, why does it
make any difference if we instantiate the variable of this type to null or
not? It shouldn't! Reference types instances must be set to null.

I also tried to run this code in non-Web project, but there it worked
without any problem. It has to be something related to ASP.NET.

Any info on this issue is appreciated.

Vagif Abilov
Oslo Norway
 
O

olrt

ms-help://MS.VSExpressCC.v80/MS.NETFramework.v20.en/dv_csref/html/235614b5-1371-4dbd-9abd-b406a8b0298b.htm
:

--------------------------------------------------------------------------------------------------------------------------
Static members are initialized before the static member is accessed for
the first time, and before the static constructor, if any is called.
--------------------------------------------------------------------------------------------------------------------------

Therefore, supposing that member b is initialized only in the Init()
call, we have :
b=null before Init called.
This said, there's something strange in Init() routine :
I would say :
if (b==null)
{
b=new B();
}
 
V

Vagif Abilov

Of course I misspelled Init routine - in real code it checks for equality to
null, as you wrote.

Regarding your quote:
Static members are initialized before the static member is accessed for
the first time, and before the static constructor, if any is called.

The big question: to WHAT they are initialized. I understand that all
unassigned reference types are initialized to null. And when I run this code
in debugger, I see that unless I explicitly assign them to null, they are
assigned to default constructor. And only when assembly is loaded in Web
project. I wonder why.

Vagif
 
O

olrt

I wrote a simple test application with your classes A and B.
I declared
static B b
instead of
static B b=null;

When I test the application, I have b=null before Init().

So static variables are initialized to null by default...

Regards.
 
B

bruce barker \(sqlwork.com\)

only in vb.net are un-initialozed variables set to null. in c# you need to
do it yourself, as the compiler doesn't emit and initalation code you don't
include. its a bug in your code. its just luck it worked in 1.1

-- bruce (sqlwork.com)
 
V

Vagif Abilov

Thanks for the effort. I also get this behavior in non-Web apps, and in some
Web apps. I will try to extract some code that demonstrates the weird
behaviour. If I manage, I will let post it.

Vagif
 
V

Vagif Abilov

Hmmm, if they are not implicitly set to null, then what value they are set
to? There must be deterministic algrorithm. And why then compiler does not
give an error? It gives an error if I try to use unassigned automatic
variable, shouldn't it do the same with member variables then?

Vagif
 
V

Vagif Abilov

I investigated further. Here is what happens.

I made a simlpe Web site consisting of an empty page. The page C# code file
looks like this:

using System;
using System.Web;

namespace StaticMemberTest
{
public class Test
{
static int A
{
get { _Default.a++; return _Default.a; }
}
}

public partial class _Default : System.Web.UI.Page
{
internal static int a = 0;

protected void Page_Load(object sender, EventArgs e)
{
Response.Write("A = " + a.ToString());
}
}
}

Steps to reproduce the problem:

1. Set the breakpoint within Page_Load
2. Start the debugger.
3. Once the breakpoint is reached, go to Watch window and type "Test.A".
4. This will trigger evaluation of Test.A getter which will increment the
value of _Default.a static variable.
5. Continue the execution, and you will see "A = 1" on the page.
6. Close the browser. Start the page now not in debug mode. It will still
display "A = 1".
7. Try to restart IIS and run the page without debugger. Still "A = 1".
8. If you try to run it in a debugger and evaluate Test.A, it will display
"A = 2". Etc.

The only way to reset the value of a static variable _Default.a is to change
the page source code, so Visual Studio will detect the change and rebuild
the page. Then _Default.a will be reset to 0.

I understand that assembly is compiled once and cached. But it looks that
also the state of static variables is stored. And this looks dangerous, and
this is not how it worked in .NET 1.1.

Vagif Abilov
Oslo Norway
 
O

olrt

Hello,
I'm afraid I have to disagree with you.
I'm using Visual C# 2005 Express and my test project compiles with no
error/warning.
So I persist to say that (with C# default compiling options) the
compiler initializes static members to null if not initialized
otherwise.
 
O

olrt

I wrote a test project like yours and :

- when I restart IIS, I stop the debugger then reconnect it (if not the
debugger doesn't stop on the breakpoint).
I have : A = 0 after IIS restart...

By the way, what kind of isolation does your application have ?
- Is it InProcess (IIS)
- Is it Medium
- Is it OutOfProcess

Mine is "Medium"...
 
V

Vagif Abilov

You are right. This is what C# specs say:

The initial value of a static variable is the default value (Section 5.2) of
the variable's type.
For purposes of definite assignment checking, a static variable is
considered initially assigned.


The default value of a variable depends on the type of the variable and is
determined as follows:

· For a variable of a value-type, the default value is the same
as the value computed by the value-type's default constructor (Section
4.1.1).

· For a variable of a reference-type, the default value is
null.
 
V

Vagif Abilov

I was using it with VS 2005 built-in Web hosting process, so it was not IIS
that controlled my site.

BTW, I received another suggestion to mark variables as ThreadStatic. This
way they will be allocated per thread. But this is probably not what I want.
 
O

olrt

Repeated the test with ASP.NET Built-in development server and no
difference with the test under IIS...
 
V

Vagif Abilov

This is weird, because I have it now reproducible on several machines. Did
you follow all steps I described (including watch window)? In watch window
you had to see "A = 1". You mean that it got reset to "A = 0" next time you
run it?

Vagif
 
O

olrt

1°) Start the debugger
2°) The debugger breaks on Page_Load
3°) ? Test.A : returns 1
4°) Continue
5°) Page prints : 1
6°) Stop the Web dev server.
7°) Start the debugger
8°) The debugger breaks on Page_Load
9°) Continue
10°) Page prints : 0
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

As I said before, static variables are not very useful in a web application.

What is it that you want to accomplish using static variables?
 
V

Vagif Abilov

Correct. If I stop Web dev server it will then print 0. But if not, then it
will keep value of 1 unless I recompile the app. I expected static data to
be recycled at least when all sessions were closed.

Vagif

1°) Start the debugger
2°) The debugger breaks on Page_Load
3°) ? Test.A : returns 1
4°) Continue
5°) Page prints : 1
6°) Stop the Web dev server.
7°) Start the debugger
8°) The debugger breaks on Page_Load
9°) Continue
10°) Page prints : 0
 
V

Vagif Abilov

I don't have much of what I couldn't turn into non-static data. Just few
class instances that did not change and were cached for performance reasons.
I discovered this when one of those instance were incorrectly initialized, I
updated its configuration and expected it to be renewed. It did not until I
recycled the ASP.NET hosting process.

I guess the lesson is to avoid singletons in Web applications.

Vagif
 

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top