I kind of posted a similar question a couple of days ago but that was more geared towards any *.Designer.cs file. This question is geared towards declaration and initialization of global variables within a class. To my knowledge, it's almost common practice (aside from the *.Designer.cs files it seems) to place all global variables at the beginning of a class definition followed by the rest of the code in any order (I prefer Getters and Setters, then Constructors, then Events, then misc functions). Well, I've seen it done and have done it myself where a global variable is set at declaration.
And I'm not referring to:
ClassA clA = new ClassA();
I'm referring to:
private int nViewMode = (int)Constants.ViewMode.Default;
Now, I've heard people say and I can agree with it on some levels, that the initialization of such variables, those variables that don't require a new statement when you declare the variable, should be done in constructors or initialization functions. However, when they stated that, they may have meant that the previous statements were fine, but not the following:
Wrong Way
private int nTotal = 100;
private int nCount = 10;
private int nDifference = nTotal - nCount;
Possible Right Way
private int nTotal = 100;
private int nCount = 10;
private int nDifference = 0;
void ClassConstructor()
{
nDifference = nTotal - nCount;
}
My questions are:
What is the most common/standard practice in such a situation?
What are the pros and cons of either?
Are these questions only relevant for some languages and not others?
My last question I thought of as I was typing this up and here's the reason. In Visual Studio 2008 it seems I can place breakpoints on global variable declarations while I don't think I could when I used to write C++ in college. Also, I believe in college, you couldn't use a variable that was declared immediately before the current variable, but then again, that was in C++. So I'm not sure if these questions are only valid for MSVS products (we used Borland in college), newer compilers, or what not. If anyone has any insight, it's appreciated. Thanks.
I believe this has been covered many times before, but there really isn't an answer other than: Whatever you do end up doing, make sure it's consistent with the code in other places in your project.
I personally prefer initializing default values outside of the constructor, unless they are calculated differently based on which constructor is used. That way, if another constructor comes along, there is no need to repeat the initialization code.
In the case of nDifference, perhaps a Property that encapsulates the logic would make more sense so:
If it doesn't get used, nDifference doesn't need to get calculated every time a new instance of the class is created.
It indicates the logic for nDifference should always be the same, regardless of which constructor is used.
The C# Language Definition guarantees that field initializations will occur in textual order within each compilation unit (file). This means that it is perfectly OK to have complex expressions in the variable initializer of static field declarations. (Instance fields, on the other hand, cannot reference other instance fields.)
If the initial value of a field depends on a previous value, then they should probably be kept together to avoid accidental re-ordering.
class Demo1 {
static int x = y + 10; // x == 10
static int y = 5;
}
class Demo2 {
static int y = 5;
static int x = y + 10; // x == 15
}
As others have stated, I would prefer to have initializers common to all instances (regardless of the chosen constructor) to occur in the declarations.
This re-ordering behavior is only true for static variable initializers. Constant initialization occurs at compile time, and the values are calculated in an order that ensures the values are initialized correctly (and circular references for constants, unlike variables, are not allowed).
class Demo3 {
const int x = y + 10; // Evaluated second. x == 15
const int y = 5; // Evaluated first.
}
You should really consider whether a calculated value needs to be stored at all, since in many cases it can be calculated at the time it is used.
class Demo4 {
int y = 5;
int x { get { return y + 10; } }
}
Personally, I like having the ability to initialize member variables where I declare them in C#, particularly if the only reason you were going to write an explicit constructor was to initialize them.
In older C# dialects (we're still on 2.0 where I work), I guess there's a consistency argument if you're populating a member Dictionary<T> or something in a constructor, since the new initializer syntax didn't show up until later. In that case, you could make the argument that you want to keep all of your initialization together. Likewise, if you're initializing some members based on constructor arguments maybe it makes more sense to keep all the initialization together rather than assigning some stuff where it's declared and other stuff in the constructor -- but if you have more than one constructor, if you don't repeat yourself you're just going to end up having some initialization in one place and the rest in another anyway so you're probably just better off assigning things where you declare them.
I prefer to initialise all fields in the constructor rather than at point of declaration. (The only exception I make to this is for static fields where I find the addition of a static constructor overkill.) My reasons are that I like to have all of the construction logic in one place and secondly to avoid the debugger jumping around confusingly when stepping through the code. However, this is just my preference and you are free to come up with whatever convention you are most comfortable with.
As others have already stated, think your convention through carefully and apply it consistently.
Related
I've been programming in C# and Java recently and I am curious where the best place is to initialize my class fields.
Should I do it at declaration?:
public class Dice
{
private int topFace = 1;
private Random myRand = new Random();
public void Roll()
{
// ......
}
}
or in a constructor?:
public class Dice
{
private int topFace;
private Random myRand;
public Dice()
{
topFace = 1;
myRand = new Random();
}
public void Roll()
{
// .....
}
}
I'm really curious what some of you veterans think is the best practice. I want to be consistent and stick to one approach.
My rules:
Don't initialize with the default values in declaration (null, false, 0, 0.0…).
Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
If the value of the field changes because of a constructor parameter put the initialization in the constructors.
Be consistent in your practice (the most important rule).
In C# it doesn't matter. The two code samples you give are utterly equivalent. In the first example the C# compiler (or is it the CLR?) will construct an empty constructor and initialise the variables as if they were in the constructor (there's a slight nuance to this that Jon Skeet explains in the comments below).
If there is already a constructor then any initialisation "above" will be moved into the top of it.
In terms of best practice the former is less error prone than the latter as someone could easily add another constructor and forget to chain it.
I think there is one caveat. I once committed such an error: Inside of a derived class, I tried to "initialize at declaration" the fields inherited from an abstract base class. The result was that there existed two sets of fields, one is "base" and another is the newly declared ones, and it cost me quite some time to debug.
The lesson: to initialize inherited fields, you'd do it inside of the constructor.
The semantics of C# differs slightly from Java here. In C# assignment in declaration is performed before calling the superclass constructor. In Java it is done immediately after which allows 'this' to be used (particularly useful for anonymous inner classes), and means that the semantics of the two forms really do match.
If you can, make the fields final.
Assuming the type in your example, definitely prefer to initialize fields in the constructor. The exceptional cases are:
Fields in static classes/methods
Fields typed as static/final/et al
I always think of the field listing at the top of a class as the table of contents (what is contained herein, not how it is used), and the constructor as the introduction. Methods of course are chapters.
In Java, an initializer with the declaration means the field is always initialized the same way, regardless of which constructor is used (if you have more than one) or the parameters of your constructors (if they have arguments), although a constructor might subsequently change the value (if it is not final). So using an initializer with a declaration suggests to a reader that the initialized value is the value that the field has in all cases, regardless of which constructor is used and regardless of the parameters passed to any constructor. Therefore use an initializer with the declaration only if, and always if, the value for all constructed objects is the same.
There are many and various situations.
I just need an empty list
The situation is clear. I just need to prepare my list and prevent an exception from being thrown when someone adds an item to the list.
public class CsvFile
{
private List<CsvRow> lines = new List<CsvRow>();
public CsvFile()
{
}
}
I know the values
I exactly know what values I want to have by default or I need to use some other logic.
public class AdminTeam
{
private List<string> usernames;
public AdminTeam()
{
usernames = new List<string>() {"usernameA", "usernameB"};
}
}
or
public class AdminTeam
{
private List<string> usernames;
public AdminTeam()
{
usernames = GetDefaultUsers(2);
}
}
Empty list with possible values
Sometimes I expect an empty list by default with a possibility of adding values through another constructor.
public class AdminTeam
{
private List<string> usernames = new List<string>();
public AdminTeam()
{
}
public AdminTeam(List<string> admins)
{
admins.ForEach(x => usernames.Add(x));
}
}
What if I told you, it depends?
I in general initialize everything and do it in a consistent way. Yes it's overly explicit but it's also a little easier to maintain.
If we are worried about performance, well then I initialize only what has to be done and place it in the areas it gives the most bang for the buck.
In a real time system, I question if I even need the variable or constant at all.
And in C++ I often do next to no initialization in either place and move it into an Init() function. Why? Well, in C++ if you're initializing something that can throw an exception during object construction you open yourself to memory leaks.
The design of C# suggests that inline initialization is preferred, or it wouldn't be in the language. Any time you can avoid a cross-reference between different places in the code, you're generally better off.
There is also the matter of consistency with static field initialization, which needs to be inline for best performance. The Framework Design Guidelines for Constructor Design say this:
✓ CONSIDER initializing static fields inline rather than explicitly using static constructors, because the runtime is able to optimize the performance of types that don’t have an explicitly defined static constructor.
"Consider" in this context means to do so unless there's a good reason not to. In the case of static initializer fields, a good reason would be if initialization is too complex to be coded inline.
Being consistent is important, but this is the question to ask yourself:
"Do I have a constructor for anything else?"
Typically, I am creating models for data transfers that the class itself does nothing except work as housing for variables.
In these scenarios, I usually don't have any methods or constructors. It would feel silly to me to create a constructor for the exclusive purpose of initializing my lists, especially since I can initialize them in-line with the declaration.
So as many others have said, it depends on your usage. Keep it simple, and don't make anything extra that you don't have to.
Consider the situation where you have more than one constructor. Will the initialization be different for the different constructors? If they will be the same, then why repeat for each constructor? This is in line with kokos statement, but may not be related to parameters. Let's say, for example, you want to keep a flag which shows how the object was created. Then that flag would be initialized differently for different constructors regardless of the constructor parameters. On the other hand, if you repeat the same initialization for each constructor you leave the possibility that you (unintentionally) change the initialization parameter in some of the constructors but not in others. So, the basic concept here is that common code should have a common location and not be potentially repeated in different locations. So I would say always put it in the declaration until you have a specific situation where that no longer works for you.
There is a slight performance benefit to setting the value in the declaration. If you set it in the constructor it is actually being set twice (first to the default value, then reset in the ctor).
When you don't need some logic or error handling:
Initialize class fields at declaration
When you need some logic or error handling:
Initialize class fields in constructor
This works well when the initialization value is available and the
initialization can be put on one line. However, this form of
initialization has limitations because of its simplicity. If
initialization requires some logic (for example, error handling or a
for loop to fill a complex array), simple assignment is inadequate.
Instance variables can be initialized in constructors, where error
handling or other logic can be used.
From https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html .
I normally try the constructor to do nothing but getting the dependencies and initializing the related instance members with them. This will make you life easier if you want to unit test your classes.
If the value you are going to assign to an instance variable does not get influenced by any of the parameters you are going to pass to you constructor then assign it at declaration time.
Not a direct answer to your question about the best practice but an important and related refresher point is that in the case of a generic class definition, either leave it on compiler to initialize with default values or we have to use a special method to initialize fields to their default values (if that is absolute necessary for code readability).
class MyGeneric<T>
{
T data;
//T data = ""; // <-- ERROR
//T data = 0; // <-- ERROR
//T data = null; // <-- ERROR
public MyGeneric()
{
// All of the above errors would be errors here in constructor as well
}
}
And the special method to initialize a generic field to its default value is the following:
class MyGeneric<T>
{
T data = default(T);
public MyGeneric()
{
// The same method can be used here in constructor
}
}
"Prefer initialization in declaration", seems like a good general practice.
Here is an example which cannot be initialized in the declaration so it has to be done in the constructor.
"Error CS0236 A field initializer cannot reference the non-static field, method, or property"
class UserViewModel
{
// Cannot be set here
public ICommand UpdateCommad { get; private set; }
public UserViewModel()
{
UpdateCommad = new GenericCommand(Update_Method); // <== THIS WORKS
}
void Update_Method(object? parameter)
{
}
}
for example:
int a;
int b;
int value = getValue(a,b);
private int getValue(int a, int b)
{
int value = a+b;
return value;
}
is the above practical or is it considered to be bad practice and would cause problem later in the development.
I realize that it's a contrived example to demonstrate what you're asking, but your example does contain a naming problem which I'll point out:
int a; // <---- right here
int b; // <---- and here
int value = getValue(a,b); // <--- and a little here
private int getValue(int a, int b)
{
int value = a+b;
return value;
}
The problem isn't in whether or not the variable names match or don't match what they're called in the method. The problem is that the variable names aren't called anything meaningful. This is considerably more of an issue than what you're asking.
Let's re-factor your method to make the example slightly less contrived...
int a;
int b;
int value = GetSum(a,b);
private int GetSum(int firstValue, int secondValue)
{
return firstValue + secondValue;
}
The method is a bit cleaner now and more intuitively reflects its purpose. Now we re-ask the question... Should a and b be renamed to match the ones in the method?
Most likely not. The names in the method have been changed to indicate their context. The method is getting a sum of two values, the first one and the second one. So what is the context of a and b? Are they also known only as the first one and the second one? Or do they convey some other meaning that's not readily available? Something like:
int milesToFirstDestination;
int milesToSecondDestination;
or:
int heightOfPersonInInches;
int heightOfStepstoolInInches;
or any other example of two values which would need to be summed for some purpose. If we added that context to the variable names then we most certainly wouldn't want to add it to the method. The method should be as general-purpose as possible, performing a single task without any concern outside of that task.
In short, it's neither good nor bad practice, because it's not something to even consider. There may be times where, by coincidence alone, the names are the same. (This can often happen with private helper methods, for example.) But they're not the same as a result of a standard or practice to be followed, but rather as a result of coincidentally having the same meaning.
Do you mean is it a good practice to always name a variable used as the argument of a method (at the call site) in the same way as the parameter of the method in the method signature? (Your example is unclear, wouldn't compile, and doesn't contain any parameters...)
No - you absolutely don't need to do that. In many cases you're calling a general purpose method which has no clue about your context - but you should name your variables in your calling method in a way which is meaningful in that context.
Only in very limited circumstances. Consider, for instance, when you want the minimum of two quantities. In the calling code, you'll know what those two quantities are. But in a general Min(a,b) method, it doesn't know or care about what those quantities mean.
If it was generally true, then each variable name could only be used once in each program. You would no longer need parameters to be passed to methods, and every variable would be global (assuming single threaded code).
We try not to write programs like that any more. For starters, it makes writing recursive code a lot less understandable.
is it good practice to use the same names for both method call and method signature parameters?
I would not have a rule that says you must or should always do this. First, it presents practical problems. Imagine:
private int Square(int n) { return n * n; }
What are you going to do here:
int a = 3;
int b = 4;
int cSquared = Square(a) + Square(b);
It's not possible, and it doesn't even make any sense, to give both a and b the same name, and to use the name n. What makes more sense is to give the parameters names that make sense in the context they are being used. So here, thinking of the Pythagorean theorem as a^2 + b^2 = c^2, we would use a and b as the local variable names. But in a different context, another name might make more sense. For example:
int length = 17;
int areaOfSquare = Square(length);
Again, it makes more sense to use a name that makes sense in the context where the method is being called. Not to use the same name in every context.
I have a class which has a group of integers, say
foo()
{
int a;
int b;
int c;
int d;
....
string s;
}
Now the question is for the best readbility, the init() function for foo(), should it look like
void init()
{
a=b=c=d=1; //for some reason they are init to 1;
s = "abc";
}
or
void init()
{
a=1;
b=1;
c=1;
d=1;
s = "abc";
}
?
The reason for a string in class is a hint of other groups of same types might present and of course, the class might grow as requirement changes
EDIT: before this question goes too far, the intention of this question was simple:
In Effective C++ item 12 (prefer initialization to assignment in constructors), Scott uses chain assignment instead of a=c; b=c; I am sure he knows when to use what, but I also remembered the books I read also recommended to use int a; int b; which in similar case of assignments. In my program I have a similar situation of a group of related individual build-in types needs to be initialized and I have found by making a chain assignment does makes it easier to read especially if the class have many other different types instance variables. It seems to contradict with books I read and my memory, hence the question.
I happen to prefer the chained version, but it's completely a matter of preference.
Please note, however, that
a = b = c = 0;
is equivalent to:
c = 0;
b = c;
a = b;
and not
a = 0;
b = 0;
c = 0;
(not that it should matter to you which assignment happens first)
My personal preference is a=b=c=d for the following reasons:
It is concise, saves lines
It conveys the concept that (a/b/c/d) are initialized to the same thing, that they are related
However, caveat:
Don't do that if a/b/c/d are not related (and just happens to be initialized to 1). You'll reduce the readability of your code. Example:
a=c=1; // Foo-function related
b=d=1; // Bar-function related
Chaining assignments like this reduces the flexibility for you in the future to assign different initial values to the variables -- because then you'll have to break them up again.
Nevertheless, my personal recommendation is to chain assignments on variables that are related on concept/usage. In actual practice, the need to change an assignment usually doesn't come up often so caveat #2 should not typically pose a problem.
Edit: My recommendation may go against published guidelines. See the comments.
I guess it is a matter of opinion which is most readable. (Clearly so ... otherwise you wouldn't be asking.)
However Oracle's "Code Conventions for the Java TM Programming Language" clearly says to use separate assignment statements:
10.4 Variable Assignments. "Avoid assigning several variables to the same value in a single statement. It is hard to read."
My opinion?
Follow your project's prescribed / agreed style rules, even if you don't like them1.
If your project doesn't (yet) have prescribed / agreed style rules:
Try to persuade the other members to adopt the most widely used applicable style rules.
If you can't persuade them / come to a consensus, then just do this informally for the major chunks of code that you write for the project1.
1 ... or get out.
This is issue about LANGUAGE DESIGN.
Please do not answer to the question until you read entire post! Thank you.
With all helpers existing in C# (like lambdas, or automatic properties) it is very odd for me that I cannot pass property by a reference. Let's say I would like to do that:
foo(ref my_class.prop);
I get error so I write instead:
{
var tmp = my_class.prop;
foo(tmp);
my_class.prop = tmp;
}
And now it works. But please notice two things:
it is general template, I didn't put anywhere type, only "var", so it applies for all types and number of properties I have to pass
I have to do it over and over again, with no benefit -- it is mechanical work
The existing problem actually kills such useful functions as Swap. Swap is normally 3 lines long, but since it takes 2 references, calling it takes 5 lines. Of course it is nonsense and I simply write "swap" by hand each time I would like to call it. But this shows C# prevents reusable code, bad.
THE QUESTION
So -- what bad could happen if compiler automatically create temporary variables (as I do by hand), call the function, and assign the values back to properties? Is this any danger in it? I don't see it so I am curious what do you think why the design of this issue looks like it looks now.
Cheers,
EDIT As 280Z28 gave great examples for beating idea of automatically wrapping ref for properties I still think wrapping properties with temporary variables would be useful. Maybe something like this:
Swap(inout my_class.prop1,inout my_class.prop2);
Otherwise no real Swap for C# :-(
There are a lot of assumptions you can make about the meaning and behavior of a ref parameter. For example,
Case 1:
int x;
Interlocked.Increment(ref x);
If you could pass a property by ref to this method, the call would be the same but it would completely defeat the semantics of the method.
Case 2:
void WaitForCompletion(ref bool trigger)
{
while (!trigger)
Thread.Sleep(1000);
}
Summary: A by-ref parameter passes the address of a memory location to the function. An implementation creating a temporary variable in order to "pass a property by reference" would be semantically equivalent to passing by value, which is precisely the behavior that you're disallowing when you make the parameter a ref one.
Your proposal is called "copy in - copy out" reference semantics. Copy-in-copy-out semantics are subtly different from what we might call "ref to variable" semantics; different enough to be confusing and wrong in many situations. Others have already given you some examples; there are plenty more. For example:
void M() { F(ref this.p); }
void F(ref int x) { x = 123; B(); }
void B() { Console.WriteLine(this.p); }
If "this.p" is a property, with your proposal, this prints the old value of the property. If it is a field then it prints the new value.
Now imagine that you refactor a field to be a property. In the real language, that causes errors if you were passing a field by ref; the problem is brought to your attention. With your proposal, there is no error; instead, behaviour changes silently and subtly. That makes for bugs.
Consistency is important in C#, particularly in parts of the language that people find confusing, like reference semantics. I would want either references to always be copy-in-copy-out or never copy-in-copy-out. Doing it one way sometimes and another way other times seems like really bad design for C#, a language which values consistency over brevity.
Because a property is a method. It is a language construct responding to a pattern of encapsulating the setting and retrieval of a private field through a set of methods. It is functionally equivalent to this:
class Foo
{
private int _bar;
public int GetBar( ) { return _bar; }
public void SetBar( ) { _bar = value; }
}
With a ref argument, changes to the underlying variable will be observed by the method, this won't happen in your case. In other words, it is not exactly the same.
var t = obj.prop;
foo(ref t);
obj.prop = t;
Here, side effects of getter and setter are only visible once each, regardless of how many times the "by-ref" parameter got assigned to.
Imagine a dynamically computed property. Its value might change at any time. With this construct, foo is not kept up to date even though the code suggests this ("I'm passing the property to the method")
So -- what bad could happen if
compiler automatically create
temporary variables (as I do by hand),
call the function, and assign the
values back to properties? Is this any
danger in it?
The danger is that the compiler is doing something you don't know. Making the code confusing because properties are methods, not variables.
I'll provide just one simple example where it would cause confusion. Assume it was possible (as is in VB):
class Weird {
public int Prop { get; set; }
}
static void Test(ref int x) {
x = 42;
throw new Exception();
}
static void Main() {
int v = 10;
try {
Test(ref v);
} catch {}
Console.WriteLine(v); // prints 42
var c = new Weird();
c.Prop = 10;
try {
Test(ref c.Prop);
} catch {}
Console.WriteLine(c.Prop); // prints 10!!!
}
Nice. Isn't it?
Because, as Eric Lippert is fond of pointing out, every language feature must be understood, designed, specified, implemented, tested and documented. And it's obviously not a common scenario/pain point.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
Why doesn't C# have local static variables like C? I miss that!!
Because they screwed up, and left out a useful feature to suit themselves.
All the arguments about how you should code, and what's smart, and you should reconsider your way of life, are pompous defensive excuses.
Sure, C# is pure, and whatchamacallit-oriented. That's why they auto-generate persistent locals for lambda functions. It's all so complicated. I feel so dumb.
Loop scope static is useful and important in many cases.
Short, real answer, is you have to move local statics into class scope and live with class namespace pollution in C#. Take your complaint to city hall.
The MSDN blog entry from 2004: Why doesn't C# support static method variables? deals with the exact question asked in the original post:
There are two reasons C# doesn't have this feature.
First, it is possible to get nearly the same effect by having a
class-level static, and adding method statics would require increased
complexity.
Second, method level statics are somewhat notorious for causing
problems when code is called repeatedly or from multiple threads, and
since the definitions are in the methods, it's harder to find the
definitions.
[author: Eric Gunnerson]
(Same blog entry in the Microsoft's own archive. The Archive.org preserved the comments. Microsoft's archive didn't.)
State is generally part of an object or part of a type, not part of a method. (The exception being captured variables, of course.)
If you want the equivalent of a local static variable, either create an instance variable or a static variable - and consider whether the method itself should actually be part of a different type with that state.
I'm not nearly as familiar with C as I am C#, but I believe you can accomplish everything you could with a local static, by using a class level static that is only used for one method. Obviously, this comes with some syntactic change, but I believe you can get whatever functionality you need.
Additionally, Eric Lippert answers questions like this on his blog a lot. Generally answered in this way: "I am asked "why doesn't C# implement feature X?" all the time. The answer is always the same: because no one ever designed, specified, implemented, tested, documented and shipped that feature." Essentially his answers generally boil down to, it costs money to add any feature, and therefore, many potential features are not implemented because they have not come out on the positive side of the cost benefit analysis.
So you want to use a static local variable in your method? Congratulations! You made another step towards becoming a real programmer.
Don't listen to all the people telling you that static locals are not "clean", that they impede "readability" and could lead to subtle and hard-to-find "bugs". Nonsense! They just say that because they are wannabe programmers! Lots of them are probably even toying around with an esoteric functional programming language during their free-time. Can you believe it? What a bunch of hipsters!
Real programmers embrace a paradigm I like to call SDD - Side effect Driven Design. Here are some of it's most important laws:
Don't be predictable! Never return the same thing from a method twice - even if it's being called with the exact same arguments!
Screw purity - let's get dirty! State, by nature, craves changing, because it is an insatiable monoid in the category of polyamorous endofunctors, i.e. it likes to be touched by as many collaborators as possible. Never miss out on an opportunity to do it the favor!
Among the tools used to code in a side effect driven manner are, of course, static local variables. However, as you noticed, C# does not support them. Why? Because over the last two decades Microsoft has been infiltrated by so called Clean Coders that favor maintainability over flexibility and control. Can you even remember the last time you have seen our beloved blue screen? Now guess whose fault is that!
But fear not! Real developers don't have to suffer from those poor design decisions. As has been mentioned before it is possible to have local variables that are kind of static with the help of lambdas.
However, the provided solution wasn't quite satisfactory. Using the previous answer our almost-SDD-compliant code would look something like this:
var inc = Increment();
var zero = inc();
var one = inc();
or
var zero = Increment()();
But that's just silly. Even a wannabe developer can see that Increment() is not a normal method and will get suspicious. A real programmer, on the other hand, can make it even more SDD-like. He or she knows that we can make a property or field look like a method by giving it the type Func<T>! We just have to initialize it by executing a lambda that in turn initializes the counter and returns another lambda incrementing the captured counter!
Here it is in proper SDD code:
public Func<int> Increment = new Func<Func<int>>(() =>
{
var num = 0;
return () => num++;
}).Invoke();
(You think the above kinda looks like an IIFE? Yes, you are right and you should be ashamed of yourself.)
Now every time you call Increment() it will return something different:
var zero = Increment();
var one = Increment();
Of course you also can make it so that the counter survives the lifetime of your instance.
That'll show them wannabe programmers!
C# is a component-oriented language and doesn't have the concept of variables outside the scope of a class or local method. Variables within a method cannot be declared static either, as you may be accustomed to doing in C. However, you can always use a class static variable as a substitute.
As a general practice, there are usually ways to solve programming problems in C# without resorting to using method-level statics. State is generally something you should design into classes and types, not methods.
Logically, yes. It would be the same as a class-level static member that was only used in that one method. However, a method-level static member would be more encapsulated. If the data stored in a member is only meant to be used by a single method, it should only be accessible by that single method.
However, you CAN achieve almost exactly the same effect in C# by creating a nested class.
Because static local variables are tied to the method, and the method is shared amongst all instances.
I've had to correct myself and other programmers who expect it to be unique per class instance using the method.
However, if you make it a static class, or static instance of a class, it's syntactically clear whether there's an instance per container-class, or one instance at all.
If you don't use these, it becomes easier to refactor later as well.
I think the idea of local statics is just as easily solved by creating public static fields to the class. Very little logical change don't you think?
If you think it would be a big logical change, I'd be interested to hear how.
class MyClass
{
public static float MaxDepthInches = 3;
private void PickNose()
{
if (CurrentFingerDepth < MyClass.MaxDepthInches)
{
CurrentFingerDepth++;
}
}
}
You can use nested-class as a workaround for this. Since C# is limiting the scope of static variables to classes, you can use nested-class as a scope.
For example:
public class Foo {
public int Increment() {
return IncrementInternal.Increment();
}
private static class IncrementInternal {
private static int counter = 0;
public static int Increment() {
return counter++;
}
}
}
Here Foo supports Increment method, but its support it by the private nested class IncrementInternal which contains the static variable as a member. And of course, counter is not visible in the context (other methods) of Foo.
BTW, if you want to access to Foo context (other members and methods) inside IncrementInternal.Increment, you can pass this as a parameter to IncrementInternal.Increment when you call it from Foo.
To keep the scope as small as possible, my suggestion is to create a nested class per each such method. And because it is probably not so common, the number of nested classes will stay small enough to maintains it.
I think it is cleaner than anonymous functions or IIFE.
You can see a live demo here.
I don't see much added benefit to local statics, if you are keeping your classes single purpose and small, there is little problem with global static pollution as the naysayers like to complain about. But here is just one other alternative.
using System;
using System.Collections;
public class Program
{
delegate bool DoWork();
public static void Main()
{
DoWork work = Foo().GetEnumerator().MoveNext;
work();
work();
work();
}
public static IEnumerable Foo()
{
int static_x = 10;
/*
do some other static stuff....
*/
main:
//repetative housework
Console.WriteLine(static_x);
static_x++;
yield return true;
goto main;
}
}
If you can imagine some sort of Lippert/Farnsworth hybrid entity announcing GOOD NEWS EVERYONE!, C# 6.0 allows the using static statement. This effectively allows you to import static class methods (and, it seems, properties and members as well) into the global scope.
In short, you can do something like this:
using NUnit.Framework;
using static Fizz.Buzz;
class Program
{
[Test]
public void Main()
{
Method();
int z = Z;
object y = Y;
Y = new object();
}
}
namespace Fizz
{
class Buzz
{
public static void Method()
{
}
public static int Z;
public static object Y { get; set; }
}
}
While this is only available in C# 6.0, from what I understand the generated assemblies should be compatible with previous .NET platforms (correct me if I'm wrong).
You can simulate it using a delegate... Here is my sample code:
public Func<int> Increment()
{
int num = 0;
return new Func<int>(() =>
{
return num++;
});
}
You can call it like this:
Func<int> inc = Increment();
inc();