try...catch and local variables

  • Thread starter Thread starter Guest
  • Start date Start date
Jon Skeet said:
It's not a compiler bug. The compiler is working exactly to the
language specification, as it should do.

I don't have a copy of the language specification. Would you please quote
the part you're referencing, where the language specification says that even
if a statement is reachable only by code paths that initialize the variable,
the compiler should still emit an "uninitialized variable" error.

Thanks,
Pete
 
Peter Duniho said:
I don't have a copy of the language specification. Would you please quote
the part you're referencing, where the language specification says that even
if a statement is reachable only by code paths that initialize the variable,
the compiler should still emit an "uninitialized variable" error.

From the C# 1.1 ECMA spec:

http://www.jaggersoft.com/csharp_standard/12.3.htm
and the pages following (click on the arrows on the right)

(I don't have a public link to a 2.0 spec handy.)

Those rules define the whether or not something is definitely assigned.
They don't say anything about things which the compiler *could* reason
about, such as:

string x;
for (int i=0; i < 10; i++)
{
// 0 < 10 so this will always be executed exactly
// once
x = "value";
}
Console.WriteLine (x);

and

string x;
if (true)
{
// This will definitely be executed
x = "value";
}
Console.WriteLine (x);

However, there *is* enough reasoning (because it has nothing to do with
the expressions within the statements) for this to be okay:

string x;
if (something)
{
x = "value";
}
else
{
x = "othervalue";
}
Console.WriteLine (x);


http://www.jaggersoft.com/csharp_standard/12.htm states that a variable
must be definitely assigned before its value can be obtained.

Any compiler which *did* allow either of the first two snippets above
to be compiled without error would be violating the spec.
 
Jon Skeet said:
[...]
Any compiler which *did* allow either of the first two snippets above
to be compiled without error would be violating the spec.

I don't understand why that is the case. The page you referred me to simply
says "a variable is said to be definitely assigned if the compiler can
prove, by static flow analysis, that the variable has been automatically
initialized or has been the target of at least one assignment".

Since it is possible by static flow analysis (that is, by analyzing the flow
of execution in a non-runtime situation) to show that both of the examples
you mention will definitely assign the variable, why is the variable still
considered unassigned?

Pete
 
It does spell out the official rules in great depth; 12.3.3.9 states
that "for" is treated as "while"; "while" is described in 12.3.3.7:
http://www.jaggersoft.com/csharp_standard/12.3.3.7.htm

This basically gives a few rules about what happens if the loop test
(typically e.g. "i<10" in "for") definitely assigns a variable, but
says nothing about the body. So that is what any compliant compiler
should do...

Marc
 
Marc Gravell said:
It does spell out the official rules in great depth; 12.3.3.9 states
that "for" is treated as "while"; "while" is described in 12.3.3.7:
http://www.jaggersoft.com/csharp_standard/12.3.3.7.htm

This basically gives a few rules about what happens if the loop test
(typically e.g. "i<10" in "for") definitely assigns a variable, but
says nothing about the body. So that is what any compliant compiler
should do...

Well, I will admit that I have no special insight into the intent of the
writers of the specification. However, my interpretation is that the
specification "says nothing about the body" because the body is itself a
statement, and the rules for that statement would be described elsewhere,
depending on the form it takes.

It's the standard recursive grammar sort of thing.

And in particular, static analysis can show in that situation that the body
statement *is* reached, and *does* initialize the variable.

So, I still don't see anything in the specification that says that even when
a statement is only reachable by code paths that initialize a variable, the
compiler should emit an "uninitialized variable" error.

Pete
 
Peter Duniho said:
And in particular, static analysis can show in that situation that the
body statement *is* reached, and *does* initialize the variable.

Clarification:

"is *always* reached". That is, there is no code path that avoids the body
statement.
 
Peter said:
Well, I will admit that I have no special insight into the intent of the
writers of the specification. However, my interpretation is that the
specification "says nothing about the body" because the body is itself a
statement, and the rules for that statement would be described elsewhere,
depending on the form it takes.

The rules for definite assignment are all laid out under the section I
pointed you at - but they're not all on one page. That's why I
explained that you should use the arrows on the right of the page to
see the rest of the details.

So, I still don't see anything in the specification that says that even when
a statement is only reachable by code paths that initialize a variable, the
compiler should emit an "uninitialized variable" error.

I have to admit to a mistake earlier - section 15.1 of the spec is
relevant here:
http://www.jaggersoft.com/csharp_standard/15.1.htm

In particular:

int x;
if (true)
{
x=0;
}
Console.WriteLine (x);

*is* valid, because the if expression is a *constant* one. The
following is invalid, because the compiler doesn't do any reasoning
about possible values of variables:


int x;
bool y = true;
if (y)
{
x=0;
}
Console.WriteLine (x);

In other words, the compiler does some *very primitive* checking. For
the "if" statement, the rules for reachability are described in
http://www.jaggersoft.com/csharp_standard/15.7.1.htm

Hope this clears things up - apologies for the previous inaccuracy
about the "if" example.

Jon
 
Back
Top