41

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?

5
  • 7
    string.IsNullOrEmpty(s) Commented Sep 13, 2012 at 20:05
  • 11
    This actually won't even compile. Variables have to be initialized. Just initialize it to null or string.Empty. Commented Sep 13, 2012 at 20:07
  • What if the variable is initialized by another thread? Are you comfortable with setting up the memory controller to generate an exception on write access? Commented Sep 13, 2012 at 20:33
  • Just make your own copy of Nullable<T> and call it Initializable<T> or something. Add an implicit casting operator from T to Initializable<T> to allow simple assignments to work, e.g. Initializable<string> myInitializableString = "Hello";. Add a T Value and a bool IsInitialized property to it, and a constructor that takes a T parameter, assigns it to Value, and sets IsInitialized to true. For convenience you can also add an implicit cast back from Initializable<T> to T, so you can write stuff like string s = myInitializableString; - assuming you find that appropriate. Commented Jun 6, 2017 at 14:54
  • This feels like an XY Problem. Why do you need to know if it's been assigned or not? Why not just have an else that throws the exception? Commented Sep 25, 2019 at 21:24

9 Answers 9

28

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.

Sign up to request clarification or add additional context in comments.

7 Comments

Isn't s == default(string) a fancy way of saying s == null?
@dasblinkenlight well yes, basically, but I think it makes the intent a bit more explicit.
@dbaseman, I disagree. It obfuscates the well known understanding of what null is for.
@KirkWoll I never thought about it that way, maybe you're right.
For value types you would still have to use Nullable<T>, since if we had private int s; instead of string, s == default(int) is exactly the same as s == 0, meaning it would be illegal in your code to assign the value 0, which isn't any better than making it illegal to assign "zanzibar" as per OP's example.
|
13

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".

4 Comments

This is not applicable to strings, because it's a reference type already.
The OP's introductory sentence stated "I want to check if a variable is initialized at run time." The type was a string only in what the OP stated was his "incomplete code" used for an example.
Don’t use boolean literals in checks, write if (x.HasValue). Boolean literals are only meaningful in initialisations (or when passed as parameters) – nowhere else.
@KonradRudolph I made the change, and in general agree with not writing out the "true" in that case, but it really isn't true that "boolean literals are only meaningful in initializations or parameters." If they had literally no semantic meaning in the context provided, it wouldn't compile.
11

Just assign it null by default, not a string value

6 Comments

what if null is a valid value for that string to be assigned in one of the if statements?
@Servy Then define a constant that represents your non-null, uninitialized value, e.g. const string UninitializedString = "zanzibar";
@PeterGluck Then that constant value now becomes "invalid", and worse, it would make debugging extraordinarily difficult because if some method just happened to return that determining why it appeared to not run at all would cause all sorts of headaches.
@Servy what's even a purpose using null as valid value?
@F8ER That would depend wildly depending on context.
|
3

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.

1 Comment

Obviously someValue isn't a method or it would be SomeValue(), but I mean "in the actual (non-simplified) case". It could still be null at any rate.
2

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.

2 Comments

Why introduce the flag and not just compare s against null?
@KirkWoll That's a great question, although I tried answering it in the answer: because someValueOne or someValueTwo could legitimately be null. (Update: apparently, the OP does not care :)
1

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.

Comments

0

I pick initialization values that can never be used, typical values include String.Empty, null, -1, and a 256 character random string generator .

6 Comments

string.Empty = "". No need to use a three times more verbose alternative. After all, we don’t use things like Int32.Zero.
I prefer String.Empty because it can't be confused with ''''. Its easier to read for me.
You shouldn’t be confused by "". Really. It’s an integral part of any programming language.
Thank you Konrad and Servy. I prefer String.Empty. If you have anything more to say on the topic of my preferences I encourage you to take this conversation to chat as it is inappropriate to continue it here.
string.Empty is definitely more intentional.
|
0

I would suggest initializing the variable with null:

MyType? myVar = null;

You can then check whether it has been set to an non-null value using:

var isSet = myVar != null;

Comments

-4

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).

3 Comments

This is a recipe for disaster. At some point you could end up with a legitimate assignment to that "uninitialized" value, causing all sorts of confusion for the programmers that need to try to determine why it's not working.
@Servy Not so. That is exactly why you use a named constant rather than sprinkling a "naked" string throughout the code. The constant can be changed as needed down the road. And note that I said that your first choice is to use null or String.Empty. In fact, const string UninitializedString = String.Empty; would be my first choice.
You don't ever sprinkle a "naked" string throughout the code in the first place. You use a solution such as this one which never uses any value to represent an "uninitialized value". That you could change it (at compile time) doesn't even significantly mitigate the dangers here. If the string could be based on user input you have no idea at compile time what the user might choose; no matter what you choose it could be wrong. It's actually not that uncommon to have a valid assignment to null or an empty string, so using that won't help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.