local variable inside static method

K

kndg

Hi all,

I thought local variable inside static method is implicitly static but
my test with threading say otherwise. Why is so?

I had always been taught to declare the variable near its usage, but it
is simply not so with static method.

I think...

static void StaticMethod()
{
string[] onetwothree = new[] { "one", "two", "three" };
// use onetwothree variable...
}

would be more elegant than

static string[] onetwothree = new[] { "one", "two", "three" };

static void StaticMethod()
{
// use onetwothree variable...
}

Am I missing something?

Regards.
 
P

Peter Duniho

kndg said:
Hi all,

I thought local variable inside static method is implicitly static but
my test with threading say otherwise. Why is so?

Why should it be so? The "static" aspect of the method simply means no
instance of the class is required in order to call the method.
Variables inside instance methods aren't persistent along with the
instance, nor are variables inside static methods persistent along with
the class.
I had always been taught to declare the variable near its usage, but it
is simply not so with static method.

I don't understand that statement at all.
I think...

static void StaticMethod()
{
string[] onetwothree = new[] { "one", "two", "three" };
// use onetwothree variable...
}

would be more elegant than

static string[] onetwothree = new[] { "one", "two", "three" };

static void StaticMethod()
{
// use onetwothree variable...
}

Am I missing something?

If you want to write the former, do it. The compiler is smart enough to
optimize the bulk of the initialization to a static initializer,
achieving practically the same performance but using the syntax you prefer.

It sounds like what you want are "static" local variables, a la C/C++.
However, C# simply doesn't have that feature. If you want a variable
that preserves its value across method calls, the variable has to exist
outside the method.

Pete
 
A

Arne Vajhøj

I thought local variable inside static method is implicitly static but
my test with threading say otherwise. Why is so?

static fields
instance fields
local variables

are 3 different types of data. They have class, instance and call scope.

I had always been taught to declare the variable near its usage, but it
is simply not so with static method.

I think...

static void StaticMethod()
{
string[] onetwothree = new[] { "one", "two", "three" };
// use onetwothree variable...
}

would be more elegant than

static string[] onetwothree = new[] { "one", "two", "three" };

static void StaticMethod()
{
// use onetwothree variable...
}

Am I missing something?

The question is not which one is most elegant. The question is
which one does what your application needs.

The first creates a new array with these values every time
the method is called.

The second use the same array throughout execution (including
multiple calls of the method).

If some code is changing the array, then that difference will
make the two pieces of code function differently.

You need to decide on which of the two functionality
you need in your app.

Arne
 
K

kndg

Why should it be so? The "static" aspect of the method simply means no
instance of the class is required in order to call the method. Variables
inside instance methods aren't persistent along with the instance, nor
are variables inside static methods persistent along with the class.

Hmm, maybe I had over-thinking it a bit and lead to my
missunderstanding. Is that mean that whether the method is static or
not, if the variable is local only to that method, each thread will have
their own variable stack and will be thread-safe. Am I right?
I had always been taught to declare the variable near its usage, but
it is simply not so with static method.

I don't understand that statement at all.
I think...

static void StaticMethod()
{
string[] onetwothree = new[] { "one", "two", "three" };
// use onetwothree variable...
}

would be more elegant than

static string[] onetwothree = new[] { "one", "two", "three" };

static void StaticMethod()
{
// use onetwothree variable...
}

Am I missing something?

If you want to write the former, do it. The compiler is smart enough to
optimize the bulk of the initialization to a static initializer,
achieving practically the same performance but using the syntax you prefer.

Hmm, interesting... Is that mean that the CLR will promote this local
variable to static variable inside a class and whenever this method is
accessed, the CLR will refer to this static variable instead . Am I
right? How do I verify this?
It sounds like what you want are "static" local variables, a la C/C++.
However, C# simply doesn't have that feature. If you want a variable
that preserves its value across method calls, the variable has to exist
outside the method.

I just don't want the overhead creating the same variable each time but
at the same time want to limit the visibility to method scope only.

Thanks for the reply.
 
K

Ken Foskey

I just don't want the overhead creating the same variable each time but
at the same time want to limit the visibility to method scope only.

Rule 1: Profile.

You can create a static member of the class that is private. This would
be consistent with what you want.

Try the static syntax in the class and the non-static in the class and
run a sample of a million calls to your subroutine. I doubt you could
measure the difference.

Focus on where the real performance problems are in your code by
profiling and don't guess.

Ken
 
K

kndg

[...]
The question is not which one is most elegant. The question is
which one does what your application needs.

Yes, my need would be the second code, but since the variable is only
used inside this method only, I thought the best practice would be to
declare the variable inside the method. But yes, since the language does
not supported it, I'll have to follow what my application need is.

As I know, "const" is implicitly static, so when I declare one inside a
method, there will be only one instance of this variable within the life
of the application.

static void SomeMethod()
{
const string str = "this is a string";
}

It seems to me that the languages does support static modifier but
through constant. But why it can't go a level futher by having the
explicit static modifier?

Regards.
 
P

Peter Duniho

kndg said:
Hmm, maybe I had over-thinking it a bit and lead to my
missunderstanding. Is that mean that whether the method is static or
not, if the variable is local only to that method, each thread will have
their own variable stack and will be thread-safe. Am I right?

Local variables are always thread-safe. Note that that doesn't mean
that the _object_ a local reference type variable refers to is
thread-safe. Just that the reference variable itself is.
[...]
If you want to write the former, do it. The compiler is smart enough to
optimize the bulk of the initialization to a static initializer,
achieving practically the same performance but using the syntax you
prefer.

Hmm, interesting... Is that mean that the CLR will promote this local
variable to static variable inside a class and whenever this method is
accessed, the CLR will refer to this static variable instead . Am I
right? How do I verify this?

No, that's not what I mean. The semantics of that declaration is that a
new instance of the array object is created each time into the method.
The compiler is required to preserve those semantics, and since an array
is mutable, it must create and discard a new object each time into and
out of the method.

But, the creation of the object can be optimized, and that is done to
the extent possible.

For a frequently-called method, with a very large object, I would not
make that a local variable. There's only so much optimization that can
be done. But for something simple like what you posted, I wouldn't
hesitate to make the initialization local to the method if that made
more sense semantically.
I just don't want the overhead creating the same variable each time but
at the same time want to limit the visibility to method scope only.

C# doesn't have any way to do that.

Pete
 
K

kndg

Rule 1: Profile.

You can create a static member of the class that is private. This would
be consistent with what you want.

Try the static syntax in the class and the non-static in the class and
run a sample of a million calls to your subroutine. I doubt you could
measure the difference.

Okay, I did the test and the difference is quite significant.

class Program
{
static string[] numbers = new[]
{
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen",
};

static string Num2String(int number)
{
return numbers[number];
}

static string Num2String2(int number)
{
string[] numbers = new[]
{
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen",
};

return numbers[number];
}

static void Main()
{
var rnd = new Random();
var sw = new System.Diagnostics.Stopwatch();

sw.Start();
for (int i = 0; i < 10000000; i++)
{
Num2String(rnd.Next(0, 20));
}
sw.Stop();

Console.WriteLine("[class scope static variable] - time taken:
{0}", sw.ElapsedMilliseconds);

sw.Reset();

sw.Start();
for (int i = 0; i < 10000000; i++)
{
Num2String2(rnd.Next(0, 20));
}
sw.Stop();

Console.WriteLine("[method scope local variable] - time taken:
{0}", sw.ElapsedMilliseconds);

Console.ReadKey();
}
}

Regards.
 
P

Peter Duniho

kndg said:
[...]
static void SomeMethod()
{
const string str = "this is a string";
}

It seems to me that the languages does support static modifier but
through constant. But why it can't go a level futher by having the
explicit static modifier?

Actually, your example is misleading, as strings are a special case in
terms of "const". Reference types are not generally allowed for "const"
variables, because the value of the variable is required to be known at
compile time.

Note also that for that one special case, there is practically no
difference between making it a real variable and a "const" variable.
Due to string interning, even a regular variable simply winds up
initialized with the reference to the specific string, which costs
practically nothing execution-wise, and is basically the same work that
would be involved in any uses of the "const" variable anyway.

As for why C# doesn't allow static local variables, that's something
you'd have to ask the designers of the language to know for sure. But,
a Google search on "why doesn't c# have static local variables" turns up
a number of worthwhile links.

Unsurprisingly, one of the most astute observations is from Jon Skeet,
and it's one which I agree with. That is, that if you find yourself
wanting a static local variable, that often suggests that the method
doesn't really belong in the class where you've put it, but rather
belongs in its own class, where the static local variable can be a class
variable instead.

Or put another way: in OOP, you have state and you have behavior. State
is variables, behavior is methods. Not only does keeping this division
rigorous help keep the code more clear, if you could have a method that
keeps its own state, it strongly suggests that the method isn't really a
behavior of the class in which you've put it, but rather is a behavior
of some as-yet-undeclared class for which the class in which it
currently exists should be a client instead.

Here are a couple of what I think are some of the more useful discussions:
http://groups.google.com/group/micr...read/thread/d21383d3fd7bf5c1/c2f6bd497472a659
http://stackoverflow.com/questions/1049689/why-doesnt-c-support-local-static-variables-like-c-does

Pete
 
P

Peter Duniho

kndg said:
[...]
Try the static syntax in the class and the non-static in the class and
run a sample of a million calls to your subroutine. I doubt you could
measure the difference.

Okay, I did the test and the difference is quite significant.

Define "significant".

Your test doesn't really illustrate anything useful, IMHO. Because a
new object does need to be created for the local variable scenario,
obviously that's going to take longer than the scenario where no new
object is created.

But most methods have some non-trivial operation that they do. The
overhead of creating an object as compared to the rest of the work the
method does is generally not an issue. It only shows up in trivial
methods, such as the ones used in your benchmark code.

I'll also point out that your test code is a very good, clear example of
the point that I raised in my other reply: that trying to make a static
local variable is a strong suggestion that the method doesn't even
belong in the class where you've put it. That would _definitely_ be
true in the example you've shown.

An "integer-to-string" map is a function of some special-purpose class,
the purpose of which is to do that mapping (and perhaps others like it,
at most) and it should not be a problem at all for your array to be a
static class variable within that kind of class.

Or, to look at the design question from the other direction, in a class
where you find that data to not be relevant to the rest of the class and
are trying to hide it in a static local variable, that kind of class
doesn't really have any business implementing that kind of mapping
anyway. It should delegate that work to a special-purpose class, for
which that _is_ a valid concern and where the static class variable
makes sense.

Pete
 
H

Harlan Messinger

kndg said:
[...]
The question is not which one is most elegant. The question is
which one does what your application needs.

Yes, my need would be the second code, but since the variable is only
used inside this method only, I thought the best practice would be to
declare the variable inside the method. But yes, since the language does
not supported it, I'll have to follow what my application need is.

As I know, "const" is implicitly static, so when I declare one inside a
method, there will be only one instance of this variable within the life
of the application.

Well, not really. "Static" (ignoring here the use of the word to denote
a class member that isn't an instance-specific member) implies that data
is stored somewhere in memory at runtime, and that that space in memory
remains allocated and maintains its value from use to use. Something
that's declared const isn't static or a variable or stored in memory at
all--it's a compile-time value.
static void SomeMethod()
{
const string str = "this is a string";
}

It seems to me that the languages does support static modifier but
through constant. But why it can't go a level futher by having the
explicit static modifier?

Again, it isn't static. It's a *constant*, and the notion of it being
static doesn't apply.
 
K

kndg

[...]
As for why C# doesn't allow static local variables, that's something
you'd have to ask the designers of the language to know for sure. But, a
Google search on "why doesn't c# have static local variables" turns up a
number of worthwhile links.

Yeah, I had searched the Google before but none of them IMO is very
convincing. Most discussions refer to static local variables inside an
*instance* method which I agree and considered a bad practice. But
static local variable inside a *static* method is IMO a different thing.
Suppose you maintain a large library of extension methods, rather than
have the variables to be declared on class scope, I think it would be
better to declare the variable inside the method where it belongs to.

Anyway, I'll read the link that you had posted and will post back if I
have futher question.

Regards.
 
A

Arne Vajhøj

Rule 1: Profile.

You can create a static member of the class that is private. This would
be consistent with what you want.

Try the static syntax in the class and the non-static in the class and
run a sample of a million calls to your subroutine. I doubt you could
measure the difference.

Okay, I did the test and the difference is quite significant.

class Program
{
static string[] numbers = new[]
{
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen",
};

static string Num2String(int number)
{
return numbers[number];
}

static string Num2String2(int number)
{
string[] numbers = new[]
{
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen",
};

return numbers[number];
}

If the optimizer does not do something for the local
variable case, then that case will do a lot of
allocation and GC'ing. That does cost something.

But the likelihood of the issue having a significant
performance impact on a real world application is very
small.

So I still think you should code after functionality
not performance.

Arne
 
A

Arne Vajhøj

Rule 1: Profile.
Try the static syntax in the class and the non-static in the class and
run a sample of a million calls to your subroutine. I doubt you could
measure the difference.

And conclude what?

That for all CPU's and .NET versions that the code will run
on for the next decade will behave just like the more or less
randomly picked systems the test was ran on?

Profiling is fine to solve a specific performance problem.

Profiling is not very good for designing code that should
perform well for the future.

Arne
 
P

Peter Duniho

kndg said:
[...]
As for why C# doesn't allow static local variables, that's something
you'd have to ask the designers of the language to know for sure. But, a
Google search on "why doesn't c# have static local variables" turns up a
number of worthwhile links.

Yeah, I had searched the Google before but none of them IMO is very
convincing. Most discussions refer to static local variables inside an
*instance* method which I agree and considered a bad practice. But
static local variable inside a *static* method is IMO a different thing.

Hopefully, the other examples explain this better. But, as a general
rule, the static method that requires a static class variable unrelated
to the rest of the class is itself a method that should not be in that
class.
Suppose you maintain a large library of extension methods, rather than
have the variables to be declared on class scope, I think it would be
better to declare the variable inside the method where it belongs to.

A "large library of extension methods" would correctly not put every
method into a single class. Rather, you would have specific classes for
each group of extension methods relevant to each other, and a static
class variable supporting a static method in a given class would not be
out of place with respect to any other methods in that class (if any).

Pete
 
K

kndg

Okay, had read the second link you posted but still couldn't get myself
convinced. Anyway, I'll leave it as it is, and since the language does
not have it, I'll have to live without it. Maybe, it will make me
rethink why the language designer choose not to have it and how the
class should be designed.

(btw, its the most constructive discussion I have read so far, and I
wonder why Paul is leaving the discussion too soon. He has presented the
best argument so far... though being cornered by the MVPs)

Regards.
 
P

Peter Duniho

kndg said:
Okay, had read the second link you posted but still couldn't get myself
convinced. Anyway, I'll leave it as it is, and since the language does
not have it, I'll have to live without it. Maybe, it will make me
rethink why the language designer choose not to have it and how the
class should be designed.

As I said, even your benchmark code shows a clear example of an
implementation that doesn't belong in some arbitrary class. If you have
a real-world example of where you are trying to use a static local
variable, then we would have something more concrete to discuss.

As it is, your ability to comprehend the justification for not
supporting static local variables is dependent on your ability and
willingness to consider a class design in which you believe some data
member should be encapsulated within a method, rather than in the
containing class, and _then_ to extrapolate the argument in favor of
refactoring that design into two separate classes.

A person predisposed to the static local variable implementation is not
necessarily the best person to rely on to do that extrapolation. :)

But, if you would provide a concise-but-complete code example that
illustrates what you feel is an appropriate, real-world use of a static
local variable, I will be happy to point out why that example really
should be factored differently.
(btw, its the most constructive discussion I have read so far, and I
wonder why Paul is leaving the discussion too soon. He has presented the
best argument so far... though being cornered by the MVPs)

If someone opens with calling the language design "stupid", IMHO they
have already failed to present "the best argument". Also, his original
code example is contrived, because it opens with the presumption of an
implementation detail that doesn't belong in correct, maintainable code.

(I can see _maybe_ putting a recursion counter in for diagnostic
purposes – though, frankly, knowing the _total_ call count for a
recursive method is dubious as compared to something more realistic,
like the _current_ call count – but you wouldn't want to leave that in
for production code, and for diagnostic purposes, who cares where the
variable is?)

Note also that Paul's approach to language design appears to be "if
there's no apparent disadvantage to the feature, toss it in", which is
quite different from the approach taken by any sane language designer.
That is, normally one approaches language design by including only those
things with clear, positive benefit that justifies the cost.

In any case, you can probably guess that it's not my opinion that Paul's
argument in favor of static local variables is anywhere close to the
"best". In fact, he not once provides a single concrete example of
where the use of a static local variable is in fact the very best
solution to a particular implementation problem.

Pete
 

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