Does C# have static local variables like C++?

  • Thread starter Thread starter Zytan
  • Start date Start date
Z

Zytan

I see that static is more restricted in C# than in C++. It appears
usable only on classes and methods, and data members, but cannot be
created within a method itself. Surely this is possible in C# in some
way? Or maybe no, because it is similar to a global variable (with its
scope restricted) which C# is dead against?

Zytan
 
Zytan said:
I see that static is more restricted in C# than in C++. It appears
usable only on classes and methods, and data members, but cannot be
created within a method itself. Surely this is possible in C# in some
way? Or maybe no, because it is similar to a global variable (with its
scope restricted) which C# is dead against?

No - methods only have "temporary" storage, and types/instances have
"longer term" storage. I've found that to lead to better encapsulation.
If you find methods which need state which isn't logically part of the
state of the object, you might consider moving the method to a
different class.
 
No - methods only have "temporary" storage, and types/instances have
"longer term" storage. I've found that to lead to better encapsulation.

Yes, I can see that.
If you find methods which need state which isn't logically part of the
state of the object, you might consider moving the method to a
different class.

I was just using it for testing some code. In practice, I don't find
much use for static vars, but they are nice to throw something
together really quick. But i respect c#'s attempt to keep things
proper.

Zytan
 
Am Tue, 27 Feb 2007 20:52:54 -0000 schrieb Jon Skeet [C# MVP]:
No - methods only have "temporary" storage, and types/instances have
"longer term" storage. I've found that to lead to better encapsulation.
If you find methods which need state which isn't logically part of the
state of the object, you might consider moving the method to a
different class.

Now, how would you then write something like this in C#?

void f()
{
static int count;
if ( count > 0 )
Debug.Writeline( "recursion level" + count.ToString() );
count++;

// -- the internals of f

count--
}



IMHO, count is only interesting within the scope of f, and therefore should
be defined in f, and nowhere else. But C# forces me to define such
variables at class level, which is stupid.

(OK, its only a minor nuisance, and other things are much worse. But
sometimes I wonder how language designers come to their results).

My 2 cents...
Paule
 
Now, how would you then write something like this in C#?
void f()
{
static int count;
if ( count > 0 )
Debug.Writeline( "recursion level" + count.ToString() );
count++;

// -- the internals of f

count--
}

IMHO, count is only interesting within the scope of f, and therefore should
be defined in f, and nowhere else. But C# forces me to define such
variables at class level, which is stupid.

Paule, you raise an interesting point. Normally, I only need the
above for quick testing code, not for production code. So, maybe the
designers thought that anything needing a C++ static local variable is
bad. But, like you said, it's only visible inside the function. But,
of course, via pass by reference, anything can be made visible to
anything.

Certainly the fact that you must declare it at the class level is
WORSE than at the method level, I agree.

Zytan
 
Am Tue, 27 Feb 2007 20:52:54 -0000 schrieb Jon Skeet [C#MVP]:
No - methods only have "temporary" storage, and types/instances have
"longer term" storage. I've found that to lead to better encapsulation.
If you find methods which need state which isn't logically part of the
state of the object, you might consider moving the method to a
different class.

Now, how would you then write something like this inC#?

void f()
{
static int count;
if ( count > 0 )
Debug.Writeline( "recursion level" + count.ToString() );
count++;

// -- the internals of f

count--
}

IMHO, count is only interesting within the scope of f, and therefore should
be defined in f, and nowhere else. ButC#forces me to define such
variables at class level, which is stupid.

(OK, its only a minor nuisance, and other things are much worse. But
sometimes I wonder how language designers come to their results).

My 2 cents...
Paule

Some where I read (may be "FAQ in C++"), even in C++ this kind of
local static variable is not safe for multi threaded applications. So,
better use functionoid.
Debi
 
| Now, how would you then write something like this in C#?
|
| void f()
| {
| static int count;
| if ( count > 0 )
| Debug.Writeline( "recursion level" + count.ToString() );
| count++;
|
| // -- the internals of f
|
| count--
| }

IMO, if f() is not using any class state, then the method should probably be
a static anyway. In which case "count" would be a static member var.
Moreover, I normally find I end up wanting "count" in class scope anyway as
many times you end up wanting to enumerate it for debug, statistics, or
other flow control in other parts of the class. I have wrote and read lots
of classes, and I never really come up with much need for local static
scope. I can think of one time similar to above, but the fix is easy and
probably not worth the change to the language. However, if I had to bet, I
would guess they add it at some point.
 
Paul Werkowitz said:
Am Tue, 27 Feb 2007 20:52:54 -0000 schrieb Jon Skeet [C# MVP]:
No - methods only have "temporary" storage, and types/instances have
"longer term" storage. I've found that to lead to better encapsulation.
If you find methods which need state which isn't logically part of the
state of the object, you might consider moving the method to a
different class.

Now, how would you then write something like this in C#?

void f()
{
static int count;
if ( count > 0 )
Debug.Writeline( "recursion level" + count.ToString() );
count++;

// -- the internals of f

count--
}



IMHO, count is only interesting within the scope of f, and therefore should
be defined in f, and nowhere else. But C# forces me to define such
variables at class level, which is stupid.

(OK, its only a minor nuisance, and other things are much worse. But
sometimes I wonder how language designers come to their results).

My 2 cents...
Paule


count has no function 'scope', it's a static after all, it has function 'visibility'.

Willy.
 
Minor amendment to the other replies: C# does have one special case
of local statics, namely constants of value types.

int Func(int y) {
const int x = 5 * 6;
return x * y;
}

This function is legal. The C# compiler will precompute x and embed
it as a literal constant in the instruction stream.
 
Am Wed, 28 Feb 2007 09:34:50 +0100 schrieb Willy Denoyette [MVP]:
count has no function 'scope', it's a static after all, it has function 'visibility'.

Willy.

Hello Willy,
I did not claim that count has "function scope". In fact, I did not say
anything about the scope of count at all.

I said that count is interesting withing the scope of f only, which is a
different thing.

And, BTW, my question is still unanswered: How do you implement the given
task in C#?

(Of course I know the answer - but it is worse) Maybe someone can enlighten
me why local statics are not in the language.


Paule.
 
Am Wed, 28 Feb 2007 00:45:17 -0500 schrieb William Stacey [C# MVP]:
| Now, how would you then write something like this in C#?
|
| void f()
| {
| static int count;
| if ( count > 0 )
| Debug.Writeline( "recursion level" + count.ToString() );
| count++;
|
| // -- the internals of f
|
| count--
| }

IMO, if f() is not using any class state, then the method should probably be
a static anyway. In which case "count" would be a static member var.

That's how you have to do it in C# (but not in other languages, e.g. C++).
In C# you have to write

void f()
{
if ( count > 0 )
Debug.Writeline( "recursion level" + count.ToString() );
count++;

// -- the internals of f

count--
}

static int count;

which, IMHO, is clearly inferior.

Moreover, I normally find I end up wanting "count" in class scope anyway as
many times you end up wanting to enumerate it for debug, statistics, or
other flow control in other parts of the class. I have wrote and read lots
of classes, and I never really come up with much need for local static
scope.

If it's not appropriate, then simply don't use static locals. I gave an
example where it would be nice. Many other situations come to mind.

I can think of one time similar to above, but the fix is easy and
probably not worth the change to the language. However, if I had to bet, I
would guess they add it at some point.

It would be a non-breaking change, and could have been added with V3. The
fact that nobody complains sheds some light on peoples mindsets. Of course
you can circumvent it - like nearly everything. If you hadn't local
variables at all, you could fix that in the same way, too.....

My 2 cents...
Paule
 
Paul Werkowitz said:
Am Wed, 28 Feb 2007 09:34:50 +0100 schrieb Willy Denoyette [MVP]:


Hello Willy,
I did not claim that count has "function scope". In fact, I did not say
anything about the scope of count at all.
I said that count is interesting withing the scope of f only, which is a
different thing.

How is it different?
If this was possible in C#, like it is in VB.NET, then the scope would still be the scope of
a "static" in the CLR/IL, which is "Application Domain scope", the *visibility* however
could be that of f().
And, BTW, my question is still unanswered: How do you implement the given
task in C#?

You can't in C#, VB.NET allows you to "declare" a local static, but this is simply
syntactic sugar, the static still becomes a *type* variable (NOT an instance nor a local
variable) , and the compiler limits its *visibility* to the declaring function only.

(Of course I know the answer - but it is worse) Maybe someone can enlighten
me why local statics are not in the language.

Because the C# language designers did not see a great value in it?


Willy.
 
Minor amendment to the other replies: C# does have one special case
of local statics, namely constants of value types.

int Func(int y) {
const int x = 5 * 6;
return x * y;

}

This function is legal. The C# compiler will precompute x and embed
it as a literal constant in the instruction stream.

I noticed that I can't do this:
const int x = MyMethod();
because MyMethod() isn't constant.

But, what I want to do is that after x is assigned, not allow it to
change. C# doesn't allow that. I wonder why.

Zytan
 
It would be a non-breaking change, and could have been added with V3. The
fact that nobody complains sheds some light on peoples mindsets. Of course
you can circumvent it - like nearly everything. If you hadn't local
variables at all, you could fix that in the same way, too.....

Oh, please. You cannot seriously compare the presence / absence of
local variables with the presence / lack of static variables local to
methods. They're not even in the same ballpark.

Here's a mindset for you: every feature that's added to C# has two
sides to it: the functionality / flexibility that it adds to the
language, and its potential for abuse. You yourself admit that this is
simply a "nice to have" that would make a few scenarios more elegant.
I agree with you.

The downside is the potential for abuse: the ability to create nasty
little functions that do something different "sometimes" because they
save state across calls.

For me, the question is not, "Why didn't they include this feature
that I would find useful?" but "Did they omit this feature because
it's not really all that useful and makes it easy to write junk code?"

C++ is an expert's language. It has many features that in an expert's
hands can result in more elegant code, but in the hands of a novice
become traps and pitfalls. C# is more workmanlike, IMHO. It's targeted
not at experts but at the average Joe Programmer, so the feature set
is different.
 
Zytan said:
I thought scope = visibility.

http://en.wikipedia.org/wiki/Variable#Scope_and_extent
"The scope of a variable is the portion of the program code for which
the variable's name has meaning and for which the variable is said to
be "visible"."

Zytan

True, visibility = lexical scope. What i really was trying to say was that the extend (or
lifetime) was different.
Consider this small sample in vb.net:

Public Class C
Public Sub Foo(item As Integer)
Static staticLocal As Integer = -1
staticLocal = item
End Sub
End Class

here "staticLocal " is declared as a static local, that means that "staticLocal " lexical
scope is equal to it's active binding in program code, that is from the beginning of Foo
till Foo returns, which is also it's visibility as far as Foo is concerned.
Now, the variable itself is a static (and really a type variable), as such has it's extend
(lifetime) bound to that of the containing AD on the CLR. It's starts life when the class
loads and ends when to AD unloads.

That why I said that it's scope did not equal it's visibility, but you are right I should
have been more explicit and used "extend" instead of "scope".

Willy.
 
Paul Werkowitz said:
That's how you have to do it in C# (but not in other languages, e.g. C++).
In C# you have to write

void f()
{
if ( count > 0 )
Debug.Writeline( "recursion level" + count.ToString() );
count++;

// -- the internals of f

count--
}

static int count;

which, IMHO, is clearly inferior.

On the contrary. It makes it clear that it's part of the state of the
type, without me having to read the *body* of a single method. The
state *will* end up as part of the state of a type or an instance (and
the fact that you used a static variable rather than an instance one
above is an interesting decision, btw) so why not make it obvious?
Then, if it clearly doesn't belong as part of the state of the
type/instance, that suggests the encapsulation is wrong and it should
be part of the state of a different type/instance.
If it's not appropriate, then simply don't use static locals. I gave an
example where it would be nice. Many other situations come to mind.

Well, I can't say I've missed them coming from C/C++. If I need state
for the sake of recursion, I tend to pass that in the recursive method
call. That's cleaner, IMO, and doesn't leave any state around for
longer than it makes sense, unlike static local variables.
It would be a non-breaking change, and could have been added with V3. The
fact that nobody complains sheds some light on peoples mindsets. Of course
you can circumvent it - like nearly everything. If you hadn't local
variables at all, you could fix that in the same way, too.....

I would personally be against the change, for the reasons above.
 
Willy Denoyette said:
You can't in C#, VB.NET allows you to "declare" a local static, but this is simply
syntactic sugar, the static still becomes a *type* variable (NOT an instance nor a local
variable)

I don't think that's quite right. If the Sub/Proc is a Shared one, it
becomes a "static variable" (C# terminology) but if it's not, it
becomes an "instance variable" (C# terminology). At least, that's what
my experimentation shows. Compile this as a DLL:

Public Class Foo

Public Sub First()
Static inFirst As Integer = 0
End Sub

Public Shared Sub Second ()
Static inSecond As Integer = 0
End Sub

End Class

The generated $STATIC$First$2001$inFirst variable is an instance
variable, but $STATIC$Second$001$inSecond is a static variable.
 

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

Back
Top