"Use of unassigned variable" -- work arounds? - c#

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.

Related

Assign variable values inside method

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

How to avoid initialization of these variable?

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.

Why declare a variable in one line, and assign to it in the next?

I often see in C# code the following convention:
some_type val;
val = something;
like
DataTable dt;
dt = some_function_returning_datatable();
or
DataTable dt = new DataTable();
dt = some_function_returning_datatable();
instead of
some_type val = something;
DataTable dt = some_function_returning_datatable();
I initially assumed that this was a habit left over from the days when you had to declare all local variables at the top of the scope. But I've learned not to dismiss so quickly the habits of veteran developers.
(In my 3rd code section will it not be wastage of memory when we assign dt first with new and then from function)
So, is there a good reason for declaring in one line, and assigning afterwards?
In my 3rd code section will it not be wastage of memory when we assign dt first with new and then from function
Yes, it will indeed. Only relatively minor - creating a useless DataTable object - but still wasteful and unclear.
So, is there a good reason for declaring in one line, and assigning afterwards?
Only if you don't have the value immediately. For example:
string x;
if (someCondition) {
// Do some work
x = someResult;
} else {
// Do some other work
x = someOtherResult;
}
Often this can be improved either using a conditional operator or extracting that code into a method. Sometimes it doesn't work out that way though.
For simple situations of:
Foo x = SomeInitializationWithNoUsefulSideEffects();
x = SomeUsefulValue();
Or
Foo x;
x = SomeUsefulValue();
You should absolutely refactor to
Foo x = SomeUsefulValue();
One other interesting situation where the declaration point does make a difference is in captured variables, although normally not the way it's intended:
int x;
for (int i = 0; i < 10; i++) {
x = SomeFunction();
actions.Add(() => Console.WriteLine(x));
}
vs
for (int i = 0; i < 10; i++) {
int x = SomeFunction();
actions.Add(() => Console.WriteLine(x));
}
In the first snippet, each delegate will capture the same variable, so they would all effectively see the last value returned from SomeFunction. In the second snippet, each delegate will capture a separate "instance" of x.
But I've learned not to dismiss so quickly the habits of veteran developers.
Dismiss them very quickly without worrying or any hesitation. It's completely meaningless to write in C#:
some_type val;
val = something;
instead of:
some_type val = something;
or:
DataTable dt = new DataTable();
dt = some_function_returning_datatable();
instead of:
DataTable dt = some_function_returning_datatable();
Anyway if you don't dismiss them in your code, the C# compiler will dismiss them when emitting the resulting IL.
Its everyone's own wish. There is no perfomance issue. Since CLR will make its own declaration how ever you declare, whether it is in one line or two line.
I always follows
int i=5;
where ever possible.
but be sure, because when you declare int i=5; in single line, CLR has to create a new instance of integer.
SomeType someVar;
someVar = new(SomeType);
and
SomeType someVar = new(SomeType);
are equivalents. Might be a a developer habit, may be that the split was necessary but has been re-factored out, but not completely.
SomeType someVar = new(SomeType);
someVar = GetSomeTypeFromSomewhereElse();
is at best inefficient coding in that the first instance will go out of scope having apparently done nothing. Course that depends on any side effects in the constructor. If there are some then we are going to have a long and painful chat during your peer review. :D
After that as others have said it's because someVar is must be declared so it can be assigned via some further logic.
When reading code, it is very useful to know which variables will change within their scope and which ones will not. A useful convention to roughly indicate this is to initialize a variable on the same line as its declaration if its value will remain constant throughout its scope, and initialize it on a line separate from its declaration if both:
Its value will be reassigned within its scope, and
That fact would not be immediately obvious
There's some room for judgment with regard to whether something is "immediately obvious"; some situations which would qualify would be:
The initialization of the variable to something that's obviously a constant value (especially if it's the default value of the type)
The reassignment of the value within a few lines of its definition
The names of the variable and the initialization expression suggest loop initialization (e.g. "var currentFoo = firstFoo;")
The longer the scope of a variable, the more likely I am to use separate initialization and declaration if the value will ever change.

A property or indexer may not be passed as an out or ref parameter

I'm getting the above error and unable to resolve it.
I googled a bit but can't get rid of it.
Scenario:
I have class BudgetAllocate whose property is budget which is of double type.
In my dataAccessLayer,
In one of my classes I am trying to do this:
double.TryParse(objReader[i].ToString(), out bd.Budget);
Which is throwing this error:
Property or indexer may not be passed as an out or ref parameter at
compile time.
I even tried this:
double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget);
Everything else is working fine and references between layers are present.
Others have given you the solution, but as to why this is necessary: a property is just syntactic sugar for a method.
For example, when you declare a property called Name with a getter and setter, under the hood the compiler actually generates methods called get_Name() and set_Name(value). Then, when you read from and write to this property, the compiler translates these operations into calls to those generated methods.
When you consider this, it becomes obvious why you can't pass a property as an output parameter - you would actually be passing a reference to a method, rather than a reference to an object a variable, which is what an output parameter expects.
A similar case exists for indexers.
This is a case of a leaky abstraction. A property is actually a method, the get and set accessors for an indexer get compiled to get_Index() and set_Index methods. The compiler does a terrific job hiding that fact, it automatically translates an assignment to a property to the corresponding set_Xxx() method for example.
But this goes belly up when you pass a method parameter by reference. That requires the JIT compiler to pass a pointer to the memory location of the passed argument. Problem is, there isn't one, assigning the value of a property requires calling the setter method. The called method cannot tell the difference between a passed variable vs a passed property and can thus not know whether a method call is required.
Notable is that this actually works in VB.NET. For example:
Class Example
Public Property Prop As Integer
Public Sub Test(ByRef arg As Integer)
arg = 42
End Sub
Public Sub Run()
Test(Prop) '' No problem
End Sub
End Class
The VB.NET compiler solves this by automatically generating this code for the Run method, expressed in C#:
int temp = Prop;
Test(ref temp);
Prop = temp;
Which is the workaround you can use as well. Not quite sure why the C# team didn't use the same approach. Possibly because they didn't want to hide the potentially expensive getter and setter calls. Or the completely undiagnosable behavior you'll get when the setter has side-effects that change the property value, they'll disappear after the assignment. Classic difference between C# and VB.NET, C# is "no surprises", VB.NET is "make it work if you can".
you cannot use
double.TryParse(objReader[i].ToString(), out bd.Budget);
replace bd.Budget with some variable.
double k;
double.TryParse(objReader[i].ToString(), out k);
Possibly of interest - you could write your own:
//double.TryParse(, out bd.Budget);
bool result = TryParse(s, value => bd.Budget = value);
}
public bool TryParse(string s, Action<double> setValue)
{
double value;
var result = double.TryParse(s, out value);
if (result) setValue(value);
return result;
}
Place the out parameter into a local variable and then set the variable into bd.Budget:
double tempVar = 0.0;
if (double.TryParse(objReader[i].ToString(), out tempVar))
{
bd.Budget = tempVar;
}
Update: Straight from MSDN:
Properties are not variables and
therefore cannot be passed as out
parameters.
This is a very old post, but I'm ammending the accepted, because there is an even more convienient way of doing this which I didn't know.
It's called inline declaration and might have always been available (as in using statements) or it might have been added with C#6.0 or C#7.0 for such cases, not sure, but works like a charm anyway:
Inetad of this
double temp;
double.TryParse(objReader[i].ToString(), out temp);
bd.Budget = temp;
use this:
double.TryParse(objReader[i].ToString(), out double temp);
bd.Budget = temp;
So Budget is a property, correct?
Rather first set it to a local variable, and then set the property value to that.
double t = 0;
double.TryParse(objReader[i].ToString(), out t);
bd.Budget = t;
Usually when I'm trying to do this it's because I want to set my property or leave it at the default value. With the help of this answer and dynamic types we can easily create a string extension method to keep it one lined and simple.
public static dynamic ParseAny(this string text, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
if (converter != null && converter.IsValid(text))
return converter.ConvertFromString(text);
else
return Activator.CreateInstance(type);
}
Use like so;
bd.Budget = objReader[i].ToString().ParseAny(typeof(double));
// Examples
int intTest = "1234".ParseAny(typeof(int)); // Result: 1234
double doubleTest = "12.34".ParseAny(typeof(double)); // Result: 12.34
decimal pass = "12.34".ParseAny(typeof(decimal)); // Result: 12.34
decimal fail = "abc".ParseAny(typeof(decimal)); // Result: 0
string nullStr = null;
decimal failedNull = nullStr.ParseAny(typeof(decimal)); // Result: 0
Optional
On a side note, if that's an SQLDataReader you may also make use of GetSafeString extension(s) to avoid null exceptions from the reader.
public static string GetSafeString(this SqlDataReader reader, int colIndex)
{
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
public static string GetSafeString(this SqlDataReader reader, string colName)
{
int colIndex = reader.GetOrdinal(colName);
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
Use like so;
bd.Budget = objReader.GetSafeString(i).ParseAny(typeof(double));
bd.Budget = objReader.GetSafeString("ColumnName").ParseAny(typeof(double));
I had the same problem (5 minutes ago) and I solved it using old style properties with getter and setter, whose use variables.
My code:
public List<int> bigField = new List<int>();
public List<int> BigField { get { return bigField; } set { bigField = value; } }
So, I just used bigField variable. I'm not the programmer, if I misunderstood the question, I'm really sorry.

Using nullable types in C#

I'm just interested in people's opinions. When using nullable types in C# what is the best practice way to test for null:
bool isNull = (i == null);
or
bool isNull = !i.HasValue;
Also when assigning to a non-null type is this:
long? i = 1;
long j = (long)i;
better than:
long? i = 1;
long j = i.Value;
I would use this:
long? i = 1;
...some code...
long j = i ?? 0;
That means, if i is null, than 0 will be assigned.
Use the forms that were specially implemented for you by the C# team. If anyone objects, tell them Anders said it was okay.
What I'm saying, flippantly, is that a lot of work went into integrating nullable types into c# to give you a good programming experience.
Note that in terms of performance, both forms compile down to the same IL, ie:
int? i = 1;
bool isINull = i == null;
int j = (int)i;
Ends up like this after the C# compiler has got to it:
int? i = 1;
bool isINull = !i.HasValue;
int j = i.Value;
I would always use the (i==null) form. It expresses what you are doing.
WRT the second question, I think either form is fine. However I'd always check it against null first and take appropriate action - perhaps wrapping that check and action up in a helper method (often it just sets a default value).
I haven't used Nullable Types in practice, but for the second, I'd actually suggest using j.GetValueOrDefault(). The documentation suggests that the latter would actually throw an InvalidOperationException in the event of a null value. Depending on the internal implementation of the explict cast operator for long?, the former might, too. I'd stick with GetValueOrDefault and treat the null/default case appropriately.
I tend to use the first on both, because as it needs to be supported later in its life-cycle, these seem easier to understand what the intent of the original writer.
Opened up Reflector. HasValue is a lookup on a boolean flag which is set when the value is changed. So in terms of cycles a lookup is going to be faster then compare.
public Nullable(T value)
{
this.value = value;
this.hasValue = true;
}
private bool hasValue;
internal T value;
public bool HasValue
{
get
{
return this.hasValue;
}
}
They're both the same, but I would use the former version on both, since it's more common in the language: comparison to null and casting to a type.
I usually tend to lean towards the first option in both scenarios, since it's more 'primitive' oriented opposed to object oriented (which was really what we were going for), but it really doesn't matter that much

Categories

Resources