So I have a bool variable like this in model.
bool Foo;
I am receiving data from server and de-serialize it model object. So whatever fields are not there in server data gets initialized to defaults. And default(bool) is false.
But value false is also an acceptable value for my variable Foo. So is there some way to check if it gets value false from server or its default.
I also have same issue with other types like int, double etc. which doesn't defaults to null.
In your place, I'd use Nullable<bool> (bool?) to your purposes. Then you will be able to check value in this way:
bool? Foo;
if(Foo.HasValue)
{
// do something with Foo.Value
}
else
{
// Foo is uninitialized
}
On my system (Microsoft (R) Visual C# Compiler version 4.7.3190.0) the accepted answer isn't complete: compiler error. Just need to initialize to null variable declaration. so:
bool? Foo = null;
if (Foo.HasValue)
{
// do something with Foo.Value
}
else
{
// Foo is uninitialized
}
Related
For some reason this if statement is invalid and it says: "Use of unassigned local variable 'I1'.
I can't figure out what is wrong with this if statement and it's bothering me.
I am using VisualStudio 2019, and I can't figure out how to fix it.
bool I1;
if (I1 == true)
{
}
The line 'Bool I1;' creates a variable, but doesn't assign it any value. Your if statement is asking "does this thing with no value equal something" and the compiler is politely letting you know that it's not bothered to do that. Presumably you'd want something like
bool I1 = GetValueOfI1Method();
if(I1) //if(I1) is functionally equivalent to if(I1 == true) but generally more readible
{
//do stuff
}
I'm guessing/hoping you have some code that could potentially assign a value to I1, if you want to use your if statement anyway what you can do is use a nullable boolean
bool? I1 = null; //use a nullable bool
//code which might assign a value to foo
...
//if statement to check if a value has been assigned and if it's true
if(I1.HasValue && I1.Value) //has anyone assigned a value to I1 and if so is that value true
{
}
Realistically you'd never bother to do the above with a bool, you'd just set it to false and run a method that might possibly set it to true (or the inverse)
I have this piece of code:
var kv = new Dictionary<int, string>() { ... };
var kv30Valid = kv.ContainsKey(30) && int.TryParse(kv[30], out var kv30Value);
myObject.nullableInt = kv30Valid ? (int?)kv30Value : null;
Note: myObject is a POCO class representing a table row, that's why nullable int.
I cannot compile my code because I get compiler error on the last line:
Local variable 'kv30Value' might not be initialized before accessing
In which case can it be unintialized and how to properly handle the case to allow valid code?
I need to populate the myObject properties with values from the kv (if they are present) parsed to their respective values.
Solution:
Moving the condition into TryParse() method solved the problem.
var kv30Valid = int.TryParse(kv.ContainsKey(30) ? kv[30] : null, out var kv30Value);
The definite assignment analyzer has limitations (as it must, yada yada yada halting problem, etc). Although we can look at this code and conclude that it'll only access kv30value if ContainsKey returned true and thus TryParse was called, it's too "separate" for the analyzer to be able to see this.
If this was inside an if block using kv30valid it might be able to see it but even then I'm not sure.
In which case can it be unintialized
When kv.ContainsKey(30) returns false, int.TryParse() isn't called, and kv30Value won't be assigned.
To simplify the issue, you have an unassigned variable:
bool test; // declared, but not assigned
if (test)
{
Console.WriteLine("Test is true");
}
This won't compile, because test is not assigned.
Now a method with an out parameter will definitely assign the variable:
bool test;
Assign(out test);
if (test)
{
Console.WriteLine("Test is true");
}
private static void Assign(out bool foo)
{
foo = true;
}
This will print "Test is true".
Now if you make the assignment conditional:
bool test;
bool condition = DateTime.Now > DateTime.Now;
if (condition)
{
Assign(out test);
}
if (test) { ... }
You'll be back at the compiler error:
CS0165: Use of unassigned local variable test
Because the assignment of test can't be guaranteed by the compiler, so it forbids further use of that variable.
Even if the usage of the variable uses the same condition:
bool test;
bool condition = DateTime.Now > DateTime.Now;
if (condition)
{
Assign(out test);
}
if (condition && test)
{
Console.WriteLine("Test is true");
}
Then still the compiler refuses you to use test.
That's exactly the same as with your && int.TryParse(..., out) code. The right side of the && is conditionally executed, thus the compiler will refuse to let you use the variable that's potentially unassigned.
Regarding the discussion below and the downvote on my answer, if you want to know the why behind all this, see the C# language specification chapter 5.3 Definite assignment. Basically put, you get this error because the compiler does a best effort attempt at statically analyzing whether the variable is assigned.
how to properly handle the case to allow valid code?
Declare it above, and assign it a sensible default value:
int kv30Value = 0;
var kv30Valid = kv.ContainsKey(30) && int.TryParse(kv[30], out kv30Value);
Or simplify the code by moving it into an if, where it'll be definitely assigned:
if (kv.ContainsKey(30) && int.TryParse(kv[30], out var kv30Value))
{
myObject.nullableInt = kv30Value;
}
I would like to make use of out or ref parameters that may not be assigned prior to calling the function. The function then is responsible for checking whether the parameter exists, and if not, creates and returns a new object.
Here is some example C# code for what I'm trying to accomplish:
public virtual object MyFunction(out object myObject)
{
if (myObject == null)
myObject = new Object();
// do some more things here...
// maybe return myObject, or perhaps something else
return myObject;
}
I would like each of the four example function calls below to be considered valid:
Object x = new Object();
MyFunction(x); // x gets passed by reference
Object y = MyFunction(x);
Object z = MyFunction();
Object u = MyFunction(null);
I get an error on line 3 telling me that Out parameter 'list' might not be initialized before accessing. Attempting to give myObject a default value gives the error A 'ref' or 'out' parameter cannot have a default value.
Is there a way to use out parameters (pass by reference) and check to see if those references have been initialized before assigning them to anything?
No, this is not possible. If you use an out parameter then you are not permitted to read the value before assigning to the variable, for the reason the compiler has already told you. If you use ref then the parameter must be initialized before it is allowed to be passed in.
Return values are most of the time the right choice when the method doesn't have anything else to return.
It only stops the caller from having to declare the variable separately. Example:
int x1;
GetValue(out x1);
Declaring a variable:
int? x1 = GetValue();
You can read more about it in thi MSDN documentation.
When you pass a null as your out parameter, e.g. by using out _, the CLR will allocate temporary storage when you first use the parameter so there is no need for the initial check that won't compile.
Step over this line (there is no exception):
The call was double result = TestMethods.DoubleValue(2.5, out _);
I want to check if a variable is initialized at run time, programmatically. To make the reasons for this less mysterious, please see the following incomplete code:
string s;
if (someCondition) s = someValue;
if (someOtherCondition) s = someOtherValue;
bool sIsUninitialized = /* assign value correctly */;
if (!sIsUninitialized) Console.WriteLine(s) else throw new Exception("Please initialize s.");
And complete the relevant bit.
One hacky solution is to initialize s with a default value:
string s = "zanzibar";
And then check if it changed:
bool sIsUninitialized = s == "zanzibar";
However, what if someValue or someOtherValue happen to be "zanzibar" as well? Then I have a bug. Any better way?
Code won't even compile if the compiler knows a variable hasn't been initialized.
string s;
if (condition) s = "test";
// compiler error here: use of unassigned local variable 's'
if (s == null) Console.Writeline("uninitialized");
In other cases you could use the default keyword if a variable may not have been initialized. For example, in the following case:
class X
{
private string s;
public void Y()
{
Console.WriteLine(s == default(string)); // this evaluates to true
}
}
The documentation states that default(T) will give null for reference types, and 0 for value types. So as pointed out in the comments, this is really just the same as checking for null.
This all obscures the fact that you should really initialize variables, to null or whatever, when they are first declared.
With C# 2.0, you have the Nullable operator that allows you to set an initial value of null for heretofore value types, allowing for such things as:
int? x = null;
if (x.HasValue)
{
Console.WriteLine("Value for x: " + num.Value);
}
Which yields:
"Value for x: Null".
Just assign it null by default, not a string value
Here's one way:
string s;
if (someCondition) { s = someValue; }
else if (someOtherCondition) { s = someOtherValue; }
else { throw new Exception("Please initialize s."); }
Console.WriteLine(s)
This might be preferable for checking if the string is null, because maybe someValue is a method that can sometimes return null. In other words, maybe null is a legitimate value to initialize the string to.
Personally I like this better than an isInitialized flag. Why introduce an extra flag variable unless you have to? I don't think it is more readable.
You can keep a separate flag that indicates that the string has been initialized:
string s = null;
bool init = false;
if (conditionOne) {
s = someValueOne;
init = true;
}
if (conditionTwo) {
s = someValueTwo;
init = true;
}
if (!init) {
...
}
This will take care of situations when s is assigned, including the cases when it is assigned null, empty string, or "zanzibar".
Another solution is to make a static string to denote "uninitialized" value, and use Object.ReferenceEquals instead of == to check if it has changed. However, the bool variable approach expresses your intent a lot more explicitly.
I would agree with Vytalyi that a default value of null should be used when possible, however, not all types (like int) are nullable. You could allocate the variable as a nullable type as explained by David W, but this could break a lot of code in a large codebase due to having to refine the nullable type to its primitive type before access.
This generic method extension should help for those who deal with large codebases where major design decisions were already made by a predecessor:
public static bool IsDefault<T>(this T value)
=> ((object) value == (object) default(T));
If you are staring from scratch, just take advantage of nullable types and initialize it as null; that C# feature was implemented for a reason.
I pick initialization values that can never be used, typical values include String.Empty, null, -1, and a 256 character random string generator .
In general, assign the default to be null or String.Empty. For situations where you cannot use those "empty" values, define a constant to represent your application-specific uninitialized value:
const string UninitializedString = "zanzibar";
Then reference that value whenever you want to initialize or test for initialization:
string foo = UnininitializedString;
if (foo == UninitiaizedString) {
// Do something
}
Remember that strings are immutable constants in C# so there is really only one instance of UninitializedString (which is why the comparison works).
This code throwing out an error:
bool status1 = (bool)Cache["cache_req_head"];
bool status2 = (bool)Cache["cache_super"];
bool status3 = (bool)Cache["cache_head"];
This is how the cache variables were set:
if (checkreqhead == true)
{
Cache["cache_req_head"] = true;
}
else if (checksuper == true)
{
Cache["cache_super"] = true;
}
else if (checkhead == true)
{
Cache["cache_head"] = true;
}
Coming from PHP background, this is awkward. The error is:
Object reference not set to an instance of an object
I'm certain it is something really simple, but probably I can't spot it.
THANKS ALL FOR HELPING :)
"Object reference not set to an instance of an object" is c# lingo for "you did something stupid with a null value"
If the Cache is empty you need to check that first
bool status1 = (bool)Cache["cache_req_head"];
should be
bool status1 = false;
if (Cache["cache_req_head"] != null)
{
status1 = (bool)Cache["cache_req_head"];
}
This is an effect of the fact that value types (like bool, int, etc) in c# can not be null. There is a wrapper, Nullable<T> with the shorthand T? that you can use if you want to allow null values for the value types.
You can cast your value to a bool? since that allows for null.
bool? status1 = (bool?)Cache["cache_req_head"];
You can then check status1 == null or status1.HasValue, to get the actual bool value you need to pick it out with status1.Value. If you pick status1.Value while status1 == null you will get a runtime exception like the one you just got.
Actually, the best way to check for whether a value exists or not in Cache is by doing:
//string is used as an example; you should put the type you expect
string variable = Cache["KEY"] as string;
if(variable!=null)
{
// do something
}
The reason why doing if(Cache["KEY"]!=null) myVariable=Cache["Key"]; is unsafe, is because the object stored in Cache["Key"] may be removed from Cache before you get a chance to assign it to myVariable and you end up thinking that myVariable holds a non-null value.
You obviously only setting one of the cache entries at a time. So unless you run the "setter" code 3 times with only 1 variable set to true, then you always going to have nulls returned.
null does not cast into bool because its a value type. Try using bool?
Since Cache[] returns an object, which is null if not set, then you're getting an exception trying to cast null into a bool.
You'd have to check if that key exists first, or you'd have to set each key to "false" as a default.