简体   繁体   中英

C# Initialization Confusion!

int?  test;
try
{
    test = (int?) Int32.Parse ("7");
} catch {}

if (test == null)
     Console.WriteLine("test is null!");
else
     Console.WriteLine("test = {0}", test);

I am have some code that does something VERY similar to this, same idea really... Creating a variable, trying to initialize it, then test to see if the initialization was a success.

Visual Studios is giving me an error saying " Use of unassigned local variable 'test' ", which is kind of annoying, this is easily fixed by setting the first line to:

int?  test = null;

but I am curious what the difference between the two lines are, because the compiler really seems to care. And to the best of my knowledge, the two lines do the same thing.

The problem is the catch block. The compiler must assume the Int32.Parse code can throw and hence hit your catch block. In the case that happens the Int32.Parse line does not complete and hence test is never assigned a value. That means the "if" line is attempting to use an uninitialized value.

You can fix this by

  1. Assigning test a value in the catch block
  2. Initializing it to null at the start of the method

you're confusing the difference between what is a variable declaration and what is variable initialization

int?  test;

simply states that you have a variable named test that is a nullable int

but

int?  test = null;

states that you have a variable named test that is a nullable int and its value is null

In VB there is no distinction, but in c# there is a difference. That's why the compiler is complaining, because if something fails in your try block then your test variable would never have been initialized.

This is an error that always occurs for locally defined variables (inside a method or property as opposed to directly within the class). Although the fact remains that the compiler need not generate this error in order to work, it does it specifically for the purpose of helping you identify potentialy unexpected results in the case of not always assigning your variables. (Someone correct me if I'm wrong, but at least some previous versions of the C# compiler didn't check for unassigned variables in some/all cases.)

Equivalently (instead of assigning test = null in the declaration), you could eliminate the error by assining test = null in the catch block, since this would mean that whatever path the code takes, the variable test gets assigned. However, I think the resolution that you have stated (assigning to null in the declaration) is the correct one - you'll see it very often in C# code that brances a lot (via try-catch statements, if statements, or whatever else) - and to be honest it's only helping you to realise to what and when you are assigning your variables, even though it may seem like a minor irritance.

您可以避免(int?)强制转换,为“ = null”字符串节省7个字节:)

test = Int32.Parse ("7");

They do the same thing, your are correct, however the variable requires the explicit assignment of null to get rid of the 'unassigned value 'error, if you want null to be considered an intentional 'not set' variable that wont throw warnings. Beyond that, Jaredpar's answer is right on target.

I believe this style is much cleaner:

try
{
    int test = Int32.Parse("7");
    Console.WriteLine("Success!");
    // add return statement for successful execution here, if any
}
catch
{
    Console.WriteLine("Disaster!");
    // other return statement here, if any
}

As for the compiler error: Any local field must be explicitly initialized on a code path before reading it. It is a common error not to initialize local fields, that's why it is an error in C#. C/C++ only warns about this, and it can yield *funny* results if it's not initialized and the value reflects the bytes that already were on the call stack.

I can only speculate on this, but it could be a performance aspect of explicitly initializing local fields, contrary to class fields: When an object is instantiated it is less costly for the run-time to initialize the object memory stream once, however initializing a local field multiple times on every method call is redundant.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM