I was reading on the net (http://www.codinghorror.com/blog/2005/07/for-best-results-dont-initialize-variables.html) that we should not initialize variables.
Somehow I dont get it. Often I just cannot avoid that. Lets look on a simple example:
public int test(string s)
{
int start = 0;
int mod = 2;
int output = 0;
foreach (int i in s)
{
output = output + (i % mod) + start;
start++;
}
return output;
}
Ok its maybe a nonsense :-) But the question is: can I avoid the initialization? Maybe its not possible for mod, because mod have to be 2 from the beginning and it will stay 2. But how about start and output? I just cannot write int start because thats always Error Use of unassigned local variable. Maybe int start = null would be better, but in this case its not gonna work too. So how to avoid this stuff?
You've misread his article. In his article he is specifically talking about initialization of variables with respect to classes. In the case you've put forth, your variables should be initialized before they can be used because they'll be immediately used.
Edit: Yes, in this specific case the int variables don't need initialization because the compiler automatically initializes an int to 0, but if this is taken to a different degree with a string or a DateTime, initialization becomes important in the context of a method.
You misread the article. The article is talking about member variables (which are automatically initialized to default values and therefore do not require explicit initialization), but you are trying to apply the rule to local variables (which are not automatically initialized and therefore require explicit initialization).
You can rewrite you method like this
public int Test(string s) {
const int mod = 2;
int start;
int output = 0;
foreach(int i in s) {
output = output + (i % mod) + start;
start++;
}
return output;
}
In this case, the start variable does not need to be initialised, and that is true whether declare in inner or outer scope.
However, the output variable does need initialisation due to the fact that it will be returned by the method, and is possible that if the loop never runs, the variable would never be initialised.
The article is talking about not to initialize variables with default values. For example,
int x = 0;
is not good. Also, you should initialize (and declare) the variable just before it's usage is a clean code.
Initialization in constructor is not just before the usage.
Related
In C# 8.0, Static Local Functions are announced
Can anyone help enlighten me as to why you would want to declare a local function as static?
The reason given in in the article:
to ensure that local function doesn't capture (reference) any variables from the enclosing scope
But:
I don't understand why would you want to ensure that?
Is there any other reason or benefits to declare it static? (performance maybe?)
The example code given in the article is:
int M()
{
int y = 5;
int x = 7;
return Add(x, y);
static int Add(int left, int right) => left + right;
}
I don't understand why would you want to ensure that?
Because it prevents you from shooting yourself in the foot. It forces the local function to be a pure function that does not modify the state of the caller.
This returns false, because the function modifies local variables of its caller:
public bool Is42()
{
int i = 42;
Foo();
return i == 42;
void Foo()
{
i = 21;
}
}
And this doesn't, because it doesn't even compile:
public bool Is42()
{
int i = 42;
Foo();
return i == 42;
static void Foo()
{
i = 21;
}
}
It prevents surprises. Of course in these simple examples the benefit isn't immediately clear, because "well it's obvious that Foo() modifies i", but in larger codebases maintained by multiple people and not properly covered by unit tests, this simple modifier prevents grief.
Capturing variables has a small additional cost as it will generate an internally used type where your captured variables are public fields. Consider a slightly modified example:
int M()
{
int y = 5;
int x = 7;
return Add();
int Add() => x + y;
}
It will actually translate to something like this:
int M()
{
int y = 5;
int x = 7;
var capturedVars = new <>c__DisplayClass0_0 { x = x, y = y };
return <M>g__Add|0_0(ref capturedVars);
}
[CompilerGenerated]
private struct <>c__DisplayClass0_0
{
public int x;
public int y;
}
[CompilerGenerated]
internal static int <M>g__Add|0_0(ref <>c__DisplayClass0_0 class_Ref1) =>
(class_Ref1.x + class_Ref1.y);
This answer from CodeCaster and this separate answer from György Kőszeg individually answer different parts of my question, so I'm bringing them both together to form the full picture for the accepted answer:
For Part 1) of my question, #CodeCaster Says:
Because it prevents you from shooting yourself in the foot. It forces the local function to be a pure function that does not modify the state of the caller.
in larger codebases maintained by multiple people and not properly covered by unit tests, this simple modifier prevents grief
So Answer 1 is: Static Local Functions ensure reliable caller method state.
For Part 2) of my question, #György Kőszeg Says:
Capturing variables has a small additional cost as it will generate an internally used type where your captured variables are public fields
And he goes on to give an example of the produced compiler code via reflector.
So Answer 2 is: Static Local Functions prevent variable capturing. Variable capturing comes at a small cost. So there is a small performance boost by declaring the local function static
I think this is just to ensure correct usage of the variables used in the local function, as the documentation says. In large and complex methods, it can prevent accidental usage of enclosing scope variables if there are variables with the same name in the local function.
In this example below, Visual Studio gives me Intellisense for a variable I haven't finished declaring / instantiating. Is this variable really in scope and could be used on the right side of it's own declaration? If not, why does Intellisense show it as an option? Is this just a quirk about how Intellisense works?
var myVariable1 = 1;
// throws compiler error, but VS offers it as an option of something to type
// when I start typing "myv"...
var myVariable2 = myVariable2;
Yes, the variable really is in scope. That's just how declarations work.
Ordinarily, it doesn't make sense to refer to the variable being declared in its own initialiser, and for local variables, the compiler will not allow you to observe the value before it's initialised. But a use of that variable that doesn't rely on it being initialised can show you that it really is in scope. For non-local variables, they have a default value, so the initialiser is well-defined if it refers to the variable.
static class Program {
static int f(out int i) {
return i = 0;
}
static void Main() {
int i = f(out i); // okay
}
static int j = j; // okay
}
I'm trying to get make method in which I can assign values to multiple variables. I don't know how many variables I will have, but I know their type. The variables can all be of different types though.
I have googled quite a bit about this, and am fairly sure that this can't be done with managed code. (Correct me if I'm wrong though)
I don't know much (read: anything) about unsafe code. Can it be done that way? Maybe pass in an array of pointers to the variables I want to initialise and do it that way?
I am basically looking for a way to pass an arbitrary number of mixed type variables to a method and assign their values inside the method... Is it pie in the sky?
EDIT 1:
Here is some code which I hope illustrates what I would like to achieve:
private void SomeMethod()
{
string a = string.empty;
int b = 0;
double c = 0;
object[] testObject = new object[] { b, c };
SetVariables(ref testObject);
}
public static void SetVariables(ref object[] Variables)
{
for (int i = 0; i < Variables.Length; i++)
Variables[i] = // The value the variable needs to have
}
After SetVariables has executed, a, b and c would be say:
a = "Some text"
b = 123
c = 1564.653
I am looking for a way to access the variables passed in as the parameter to SetVariables and modify their value. I guess that would mean accessing their storage location in memory, hence my thinking that I might need pointers?
EDIT 2:
My question here should give a better indication of the context in which I am trying to do this.
I will only be dealing with basic types: string, int, double and bool for the variables I want to assign to.
The data I am assigning from is in text format and has a variable number of fields. Each field should map to one of the input variable in the order in which the variables are passed in. If the order does not match there will be a misasignment at best or a type error at worst, but it is up to the user to make sure that the variables match the data.
What you are trying to do doesn't work well in C#. It is really a language thing, not a "managed vs un-managed" thing.
It usually doesn't come up that much, because in your sample code, you do know that you have 2 variables. You had to type them to enter them into the array.
If SetVariables() is going to be called from a lot of places in the code with different numbers of parameters, you could make a bunch of overloads of the method (with 1 parameter, 2 parameters, 3 parameters, etc).
But really to be honest, typically when you run into this case it is because you are doing something in an un-wise way.
Thinking more about it, how would the line:
Variables[i] = // The value the variable needs to have
would be expected to work in this scenario. How does it know what to set an arbitrary variable to, since it can be of any type? Also, what stops it from messing up the variable assignments if I change the call from passing in variable b, c to reversing them c, b?
Logically, it starts to fall apart.
I guess what I'm trying to say is that C# doesn't support that very well, but it typically doesn't need to, because it rarely makes sense.
Trying to think of a working solution anyway; I would just have SetVariables just return the values, but not take in the parameters. It should be the other function's job to assign its variables. If you need to know the types, then just pass the types:
public object[] GetValues(params Type types)
{
var result = new object[types.length];
for (int i = 0; i < types.length; i++)
{
if(types[i] == typeof(string))
result[i] = "foo";
if(types[i] == typeof(int))
result[i] = -1;
}
return result;
}
public void DoStuff()
{
var data = GetValues(typeof(string), typeof(int), typeof(string));
string foo1 = (string)data[0];
int someNumber = (int)data[1];
string foo2 = (string)data[2];
}
Its ugly, but it works...
Here is an example adapted from this answer to a similar question, unfortunately your problem is a little difficult to solve and there really isn't a simple way to accomplish what you want.
private static void SomeMethod() {
string a = string.Empty;
int b = 0;
double c = 0;
SetVariables(x => a = (string)x
, x => b = (int)x
, x => c = (double)x);
Console.WriteLine("a: {0}\nb: {1}\nc: {2}", a, b, c);
}
public static void SetVariables(params Action<object>[] setters) {
var tokens = new object[] { "Hello", 10, 14.235 };
for (int i = 0; i < setters.Length; i++)
setters[i](tokens[i]); // Assumed this is read and initialized properly
}
I'll admit this has a bit of a smell to it, but since you really have to account for a variable input it should get you closer to what you want without adding an excessive amount of complexity.
I think you are pretty close to the answer yourself. Assuming that the value assigned to the variable is only based off what type it is then assuming you use the code you posted above you can compare the value type with a typeof() check during your for loop:
if(Variables[i].GetType() == typeof(int)){
//...do stuff
}
//etc...until you have an if for each data type you expect you might find
here is a link to the typeof documentation
I'm assuming you have looked at how to use reference types but just in case look here
can anyone suggest me the exact use of out keyword as a paramter, and how its connected for returning multiple values from the function, as in this POST, i am confused with out variable with normal variable. can anyone help me for this.
This is frequently confusing, and I think the MSDN documentation actually is a bit "clear only if already known". That is, it is correct, but it really only makes sense if you already understand the concept.
Here's how I think of it.
A regular parameter makes a copy of the value of the argument. When you say:
static int M(int z) { z = z + 1; return z; }
...
int x = 123;
int y = M(x);
That is just like you said:
int x = 123;
int z = x; // make a copy of x
z = z + 1;
int y = z;
A ref or out parameter make an alias for an existing variable. When you say
static void N(ref int q) { q = q + 1; }
...
int x = 123;
N(x);
That is the same as saying:
int x = 123;
// MAGIC: q is now an another name for variable x
q = q + 1;
q and x are two different names that refer to the same variable. Incrementing q also increments x because they are the same. z and x in the previous example are two different names that refer to two different variables. Incrementing z does not change x.
Summing up: "out" and "ref" just mean "do not make a new variable; rather, temporarily make a second name for an existing variable".
Is that now clear?
UPDATE: I did not say what the difference between "out" and "ref" is. The difference is simple. On the "caller" side, a "ref" must be a definitely assigned variable before the method is called. An "out" need not be. On the "callee" side, a "ref" may be read before it is written to, but an "out" must be written to before it is read. Also, an "out" must be written to before control leaves the method normally.
MSDN documentation already does a great job explaining this:
The out keyword causes arguments to be passed by reference. This is
similar to the ref keyword, except that ref requires that the variable
be initialized before being passed. To use an out parameter, both the
method definition and the calling method must explicitly use the out
keyword. For example:
class OutExample
{
static void Method(out int i)
{
i = 44;
}
static void Main()
{
int value;
Method(out value);
// value is now 44
}
}
It's very frequently used in a pattern that "tries" to get a value, something like:
int result;
if(Int32.TryParse("123", out result))
{
Console.WriteLine(result + 1);
}
out keyword should be used when you want to:
a) Allow your function to modify specific variable from calling code stack AND
b) enforce setting this variable value inside your function
MSDN is always a good place to start
In most languages c# included you can pass values in 2 ways, by value, by reference.
by value gives the method a copy of your data, so changing the data wont have any effect on the original data
by reference essentially gives the method the memory address of your data, so if the method modifies the data, it changes the original.
Out is a special type of ref, in that you do not need to initialise the variable before you call the method, it can be called with null being passed in. and it MUST be set by the method.
Another way you can think of it (from the outside code's point of view) is:
val = read only
ref = read/write
out = write only.
http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx
out keyword is good if you want to return multiple values of pre-defined types (for example an int, a List<string> and a DateTime), and you don't want to create a new class just for this purpose.
Ok,
let look at the usual pattern for this kind of function - the TrySomething.
Suppose you have a function that might succeed giving you an value or not but you don't won't to use an exception for this because you don't want the overhead or it's a common trait.
Then you normaly return true if the method suceeded and false if not. But where would you put your outputvalue to?
One possible answer is using an out parameter like this:
bool TrySomething(MyInputType input, out MyOutputType output)
{
output = default(MyOutputType);
/* ... Try getting the answer ... */
if (!successful)
return false;
output = successfulOutput;
return true;
}
Remark:
Or you might consider using a Tuple<bool,MyOutputType> and indeed F# interpretes the pattern above as resulting in such a tuple by itself.
Now I've long known and been use to this behavior in C#, and in general, I like it. But sometimes the compiler just isn't smart enough.
I have a small piece of code where right now my workaround isn't a big problem, but it could be in similar cases.
bool gap=false;
DateTime start; // = new DateTime();
for (int i = 0; i < totaldays; i++)
{
if (gap)
{
if (list[i])
{
var whgap = new WorkHistoryGap();
whgap.From = start; //unassigned variable error
whgap.To = dtFrom.AddDays(i);
return whgap;
}
}
else
{
gap = true;
start = dtFrom.AddDays(i);
}
}
The problem I'm seeing is what if you had to do this with a non-nullable struct that didn't have a default constructor? Would there be anyway to workaround this if start wasn't a simple DateTime object?
sometimes the compiler just isn't smart enough
The problem you want the compiler to solve is equivalent to the Halting Problem. Since that problem is provably not solvable by computer programs, we make only a minimal attempt to solve it. We don't do anything particularly sophisticated. You're just going to have to live with it.
For more information on why program analysis is equivalent to the Halting Problem, see my article on the subject of deducing whether the end point of a method is reachable. This is essentially the same problem as determining if a variable is definitely assigned; the analysis is very similar.
http://blogs.msdn.com/b/ericlippert/archive/2011/02/24/never-say-never-part-two.aspx
what if you had to do this with a non-nullable struct that didn't have a default constructor?
There is no such animal. All structs, nullable or otherwise, have a default constructor.
Would there be anyway to workaround this if start wasn't a simple DateTime object?
The expression default(T) gives you the default value for any type T. You can always say
Foo f = default(Foo);
and have a legal assignment. If Foo is a value type then it calls the default constructor, which always exists. If it is a reference type then you get null.
The compiler has no way of knowing that you are guaranteed to set DateTime because of your gap variable.
Just use
DateTime start = DateTime.Now;
and be done with it.
Edit Better yet, on second glance through your code, use
DateTime start = dtFrom;
There is no such thing as a default constructor in a struct. Try it:
struct MyStruct {
public MyStruct() {
// doesn't work
}
}
You can have a static constructor, but you cannot define a default constructor for a struct. That's why there's the static method Create on so many structures, and why you can say new Point() instead of Point.Empty.
The "default constructor" of any struct always initializes all of its fields to their default values. The Empty static field of certian types is for convenience. It actually makes zero difference in performance because they're value types.
Looks to me like your bool gap and the DateTime start are really the same thing. Try refactoring like this:
DateTime? gapStart = null ;
for (int i = 0; i < totaldays; i++)
{
if ( gapStart.HasValue )
{
if (list[i])
{
var whgap = new WorkHistoryGap();
whgap.From = gapStart.Value ; //unassigned variable error
whgap.To = dtFrom.AddDays(i);
return whgap;
}
}
else
{
gapStart = dtFrom.AddDays(i);
}
}
[edited to note: please post code samples that will...oh...actually compile. It makes it easier.]
[further edited to note: you set gap to true and set your start value the first time through the loop. Further refactor to something like this:]
DateTime gapStart = dtFrom.AddDays( 0 );
for ( int i = 1 ; i < totaldays ; i++ )
{
if ( list[i] )
{
var whgap = new WorkHistoryGap();
whgap.From = gapStart.Value; //unassigned variable error
whgap.To = dtFrom.AddDays( i );
return whgap;
}
}
Why are you trying to work around the design of the language? Even if the compiler could work out your entire loop in advance, which seems needlessly complex on the part of the compiler, how does it know that exceptions cannot be thrown in portions of your code? You MUST assign a value to start because you use it later in the code, possibly before its (according to you) inevitable assignment.