Please confirm this is a MSFT bug | | |
Hi there,
Before I notify MSFT, can someone confirm this is in fact a compiler bug (it
seems pretty obvious but I'm fairly new to C#). The following code
(erroneously) generates compiler error CS0177 (The out parameter 'Whatever'
must be assigned to before control leaves the current method).
public void SomeFunc(out string Whatever)
{
bool Continue = ShouldWeContinue();
if (Continue)
{
Whatever = "Continue";
}
if (!Continue)
{
Whatever = "Didn't continue";
}
} | | | | re: Please confirm this is a MSFT bug
Jake,
The compiler error is correct - you must assign a value to 'Whatever'
before leaving the method. Your code could easily be updated to do this
as so:
bool Continue = ShouldWeContinue();
if (Continue)
Whatever = "Continue";
else
Whatever = "Didn't continue";
Hope this helps.
Dan Manges
Jake Forson wrote:[color=blue]
> Hi there,
>
> Before I notify MSFT, can someone confirm this is in fact a compiler bug (it
> seems pretty obvious but I'm fairly new to C#). The following code
> (erroneously) generates compiler error CS0177 (The out parameter 'Whatever'
> must be assigned to before control leaves the current method).
>
> public void SomeFunc(out string Whatever)
> {
> bool Continue = ShouldWeContinue();
> if (Continue)
> {
> Whatever = "Continue";
> }
>
> if (!Continue)
> {
> Whatever = "Didn't continue";
> }
> }[/color] | | | | re: Please confirm this is a MSFT bug
> Jake,[color=blue]
>
> The compiler error is correct - you must assign a value to 'Whatever'
> before leaving the method. Your code could easily be updated to do this
> as so:
>
> bool Continue = ShouldWeContinue();
> if (Continue)
> Whatever = "Continue";
> else
> Whatever = "Didn't continue";
>
> Hope this helps.[/color]
Thanks for the feedback. It does assign it in all cases however which is why
I consider it a bug. | | | | re: Please confirm this is a MSFT bug
As written, yes - we can observe that it will always have a value by the
time it exits.
However: if the variable was a field, or if the variable was used in a (2.0)
anonymous delegate (as a /captured/ variable), then it would be possible for
(without it being obvious in the code) another thread to alter the value of
Continue between the two calls, which incidentally may or may-not be spotted
depending on volatility / memory-barriers. Given this, it makes a lot of
sense for me for the compiler to follow the "keep it simple" principle, and
consider all three cases equally - otherwise you would have to remember daft
rules about when each applies, and making a change (like using it in an
anonymous delegate) would suddenly cause unrelated code to not compile.
Does that make sense?
Marc | | | | re: Please confirm this is a MSFT bug
"Jake Forson" <no_spam@_nospam.com> wrote in message
news:eSyB8VEnGHA.1976@TK2MSFTNGP02.phx.gbl...[color=blue][color=green]
>> Jake,
>>
>> The compiler error is correct - you must assign a value to 'Whatever'
>> before leaving the method. Your code could easily be updated to do this
>> as so:
>>
>> bool Continue = ShouldWeContinue();
>> if (Continue)
>> Whatever = "Continue";
>> else
>> Whatever = "Didn't continue";
>>
>> Hope this helps.[/color]
>
> Thanks for the feedback. It does assign it in all cases however which is
> why I consider it a bug.[/color]
Not so much a bug as the compiler not being as smart as it could. From the
compilers point of view there are 2 seperate IF statements. There is only so
far the compiler can go when determining code paths.
It probably doesn't consider the actual contents of the if statements, so
worries about the consequences if neither one is true.
:-)
ChrisM. | | | | re: Please confirm this is a MSFT bug
"Jake Forson" <no_spam@_nospam.com> wrote in message
news:eSyB8VEnGHA.1976@TK2MSFTNGP02.phx.gbl...[color=blue][color=green]
>> Jake,
>>
>> The compiler error is correct - you must assign a value to 'Whatever'
>> before leaving the method. Your code could easily be updated to do this
>> as so:
>>
>> bool Continue = ShouldWeContinue();
>> if (Continue)
>> Whatever = "Continue";
>> else
>> Whatever = "Didn't continue";
>>
>> Hope this helps.[/color]
>
> Thanks for the feedback. It does assign it in all cases however which is
> why I consider it a bug.[/color]
Yes, it does assign it in all cases, but are they supposed to check every if
statement to see if it is an exact opposite of every other if statement.
Seems pretty silly and I don't see it as a bug.
This code:
private bool TestThis()
{
bool Continue = ShouldWeContinue();
if (Continue)
{
return true;
}
if (!Continue)
{
return false;
}
}
Produces "Not all code paths return a value" which I don't see as a bug
either. Yes, these simple examples are easy to check. But, it could
actually get way too complex to check. | | | | re: Please confirm this is a MSFT bug
> As written, yes - we can observe that it will always have a value by the[color=blue]
> time it exits.
>
> However: if the variable was a field, or if the variable was used in a
> (2.0) anonymous delegate (as a /captured/ variable), then it would be
> possible for (without it being obvious in the code) another thread to
> alter the value of Continue between the two calls, which incidentally may
> or may-not be spotted depending on volatility / memory-barriers. Given
> this, it makes a lot of sense for me for the compiler to follow the "keep
> it simple" principle, and consider all three cases equally - otherwise you
> would have to remember daft rules about when each applies, and making a
> change (like using it in an anonymous delegate) would suddenly cause
> unrelated code to not compile.
>
> Does that make sense?[/color]
Thanks for the info. While the KISS principle may apply here (on that we
agree), I'm at odds with your other points. It's certainly easier to parse
code without worrying about trapping this type of scenario and even
beneficial if it imrpoves compiler performance and robustness, but it's
still legal IMO (or should be). I doubt the C# standard says otherwise (I'd
be surprised to find out). As for your threading point, I don't follow this
at all :) I'm not familiar with threading in .NET yet, but in the usual
case, it's normally up to the programmer to properly synchronize access to
shared resources accordingly. I don't see how threading plays into this
scenario at all (assuming the programmer is doing his job but again, I'm not
familiar with the .NET threading model). In any case, while this is hardly a
blocking issue, it does force the programmer to re-work what appears to be
perfectly legal code (and this contrived example is just a dumbed down
version of what I really wanted to do but can't). Anyway, thanks again for
the feedback. | | | | re: Please confirm this is a MSFT bug
> Not so much a bug as the compiler not being as smart as it could. From the[color=blue]
> compilers point of view there are 2 seperate IF statements. There is only
> so far the compiler can go when determining code paths.
> It probably doesn't consider the actual contents of the if statements, so
> worries about the consequences if neither one is true.[/color]
Unless the standard says otherwise (or defines it as an implementation
detail which prevents you from writing portable code so it seems very
unlikely), it is therefore a bug IMO. The compiler is supposed to parse the
code according to the rules so as long as I've assigned something to my
"out" parameter, I've met my own burden so the compiler should meet its :) | | | | re: Please confirm this is a MSFT bug
Hi,
Personally I find the compiler answer correct.
It would not happen if you do
if (Continue)
{
Whatever = "Continue";
}
else
Whatever = "Didn't continue";
And in any case it's not a bug, it would be more like an optimization
--
--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation
"Jake Forson" <no_spam@_nospam.com> wrote in message
news:%23%23BUOPEnGHA.4532@TK2MSFTNGP02.phx.gbl...[color=blue]
> Hi there,
>
> Before I notify MSFT, can someone confirm this is in fact a compiler bug
> (it seems pretty obvious but I'm fairly new to C#). The following code
> (erroneously) generates compiler error CS0177 (The out parameter
> 'Whatever' must be assigned to before control leaves the current method).
>
> public void SomeFunc(out string Whatever)
> {
> bool Continue = ShouldWeContinue();
> if (Continue)
> {
> Whatever = "Continue";
> }
>
> if (!Continue)
> {
> Whatever = "Didn't continue";
> }
> }
>
>
>[/color] | | | | re: Please confirm this is a MSFT bug
Hi,
[color=blue]
> Thanks for the feedback. It does assign it in all cases however which is
> why I consider it a bug.[/color]
Well, you selected the most obvious option, bool which only have two
possible values. what if instead you select an enum (or in an even more
extreme case an int) ?
Would you expect the compiler to keep track if you used all the possible
values?
Too much work IMO.
--
--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation | | | | re: Please confirm this is a MSFT bug
> Hi,[color=blue]
>
> Personally I find the compiler answer correct.
>
> It would not happen if you do
>
> if (Continue)
> {
> Whatever = "Continue";
> }
> else
> Whatever = "Didn't continue";
>
>
> And in any case it's not a bug, it would be more like an optimization[/color]
I don't see how it qualifies as an optimization :) A language is defined by
a standard which sets down all rules that you must follow. Unless the
standard stipulates certain rules or conventions that render this example
illegal (I don't have a copy in front of me to check), then I'm not
violationg any rules so the compiler is in error :) | | | | re: Please confirm this is a MSFT bug
>> Thanks for the feedback. It does assign it in all cases however which is[color=blue][color=green]
>> why I consider it a bug.[/color]
>
> Well, you selected the most obvious option, bool which only have two
> possible values. what if instead you select an enum (or in an even more
> extreme case an int) ?
> Would you expect the compiler to keep track if you used all the possible
> values?
>
> Too much work IMO.[/color]
Again, the compiler doesn't define the language. The standard does and the
compiler must follow it even if it doesn't like it. Otherwise it's not a
compliant compiler and this should be stipulated somewhere. In this case
especially, since MSFT created C#, they're not following their own rules
(assuming this example is in fact legal - I wouldn't mind hearing from a
language lawyer on the subject) | | | | re: Please confirm this is a MSFT bug
"Jake Forson" <no_spam@_nospam.com> wrote in message
news:exfBIxEnGHA.692@TK2MSFTNGP04.phx.gbl...[color=blue][color=green]
>> Not so much a bug as the compiler not being as smart as it could. From
>> the compilers point of view there are 2 seperate IF statements. There is
>> only so far the compiler can go when determining code paths.
>> It probably doesn't consider the actual contents of the if statements, so
>> worries about the consequences if neither one is true.[/color]
>
> Unless the standard says otherwise (or defines it as an implementation
> detail which prevents you from writing portable code so it seems very
> unlikely), it is therefore a bug IMO. The compiler is supposed to parse
> the code according to the rules so as long as I've assigned something to
> my "out" parameter, I've met my own burden so the compiler should meet its
> :)[/color]
Yeeeaaa...
OK, so granted it is clear (to you and me) that in your case, either one or
the other of the if statements will definatly be true, and the compiler
could (I suppose) be smart enough to work that out.
However, how complex to you expect the compiler to get?
How about:
int testValue;
testValue = GetMyTestValue();
if (testValue <=5)
Whatever = "Continue";
if (testValue >=6)
Whatever = "Dont Continue";
should that compile?
what then if we change the first line to
double testValue;
I think it is also true that your original way of writing the method is
probably not the 'correct' way to write it. If it is written in the
'correct' way, that is as an IF..THEN..ELSE then the compiler is perfectly
happy with it.
;-P
ChrisM. | | | | re: Please confirm this is a MSFT bug
> I don't see how threading plays into this scenario at all (assuming the[color=blue]
> programmer is doing his job but again <snip>[/color]
The compiler does not (nor should not) enforce thread-synchronisation around
fields; this means that from the compiler's point-of-view the scenario I
posted is entirely plausible, so (if a field of captured variable) it *must*
barf at this.
[color=blue]
> your threading point, I don't follow this at all <snip>[/color]
The following code demonstates the /captured/ variable issue:
bool Continue = ShouldWeContinue();
something.SomeEvent += delegate {
DoSomething(ref Continue);
};
if (Continue) // ... etc as before
Now, SomeEvent could fire between the two "if" tests, changing the value of
Continue, and hence our return-variable might never be assigned. So: even in
a very simple example it is impossible to define a single behaviour that
works consistently for variables, fields and captured variables, *let alone*
properties and methods. As Jeff observes, with only a few more lines of code
it could get *must* more complex, too much so for either the compiler or
developer to validate that each route leaves a valid state.
So: it would only ever work with the most noddy of examples : why complicate
the compiler for such a trivial case? Why not just be consistent and
*either* assign a default value at initialisation, *or* use if/else so that
each route can be easily traced.
Marc | | | | re: Please confirm this is a MSFT bug
> OK, so granted it is clear (to you and me) that in your case, either one[color=blue]
> or the other of the if statements will definatly be true, and the compiler
> could (I suppose) be smart enough to work that out.
> However, how complex to you expect the compiler to get?
>
> How about:
>
> int testValue;
> testValue = GetMyTestValue();
> if (testValue <=5)
> Whatever = "Continue";
> if (testValue >=6)
> Whatever = "Dont Continue";
>
> should that compile?[/color]
Of course it should if the standard says so. The standard wags the
(compiler's) tail, not the other way around.
[color=blue]
> I think it is also true that your original way of writing the method is
> probably not the 'correct' way to write it. If it is written in the
> 'correct' way, that is as an IF..THEN..ELSE then the compiler is perfectly
> happy with it.[/color]
There's nothing incorrect about it at all. It may be verbose, less efficient
(potentially) , etc., but it's not "incorrect" as far as the language is
concerned (again, subject to what the standard says). Note that this isn't a
real world example anyway but is effectively the same as what I was trying
to do (which was much cleaner). | | | | re: Please confirm this is a MSFT bug
Jake Forson wrote:[color=blue][color=green][color=darkred]
>>> Thanks for the feedback. It does assign it in all cases however
>>> which is why I consider it a bug.[/color]
>>
>> Well, you selected the most obvious option, bool which only have two
>> possible values. what if instead you select an enum (or in an even
>> more extreme case an int) ?
>> Would you expect the compiler to keep track if you used all the
>> possible values?
>>
>> Too much work IMO.[/color]
>
> Again, the compiler doesn't define the language. The standard does
> and the compiler must follow it even if it doesn't like it. Otherwise
> it's not a compliant compiler and this should be stipulated
> somewhere. In this case especially, since MSFT created C#, they're
> not following their own rules (assuming this example is in fact legal
> - I wouldn't mind hearing from a language lawyer on the subject)[/color]
See section 12.3.5 of ECMA-334. http://www.ecma-international.org/pu...T/Ecma-334.pdf
In your case, the compiler wins - it's not required to do the level of
analysis to prove that the two if statements in your example are mutually
exclusive, so your two if statements don't constitute definite assignment to
the variable according to the rules.
-cd | | | | re: Please confirm this is a MSFT bug
>[color=blue][color=green]
>> your threading point, I don't follow this at all <snip>[/color]
>
> The following code demonstates the /captured/ variable issue:
>
> bool Continue = ShouldWeContinue();
> something.SomeEvent += delegate {
> DoSomething(ref Continue);
> };
> if (Continue) // ... etc as before[/color]
[color=blue]
> Now, SomeEvent could fire between the two "if" tests, changing the value
> of Continue, and hence our return-variable might never be assigned. So:
> even in a very simple example it is impossible to define a single
> behaviour that works consistently for variables, fields and captured
> variables, *let alone* properties and methods. As Jeff observes, with only
> a few more lines of code it could get *must* more complex, too much so for
> either the compiler or developer to validate that each route leaves a
> valid state.[/color]
I'm not certain whether my point is defensible or even valid since I'm not
all that familiar with .NET threading. However, your example wouldn't
normally apply at all in this case (assuming I'm not out in left field as
far as .NET is conerned). If an event fires it will do so on another thread
and if that thread is going to modify "Continue" in anyway, then someone
(the programmer) needs to synchronize access to "Continue" using whatever
synchronization primitives the language (.NET) offers. IMHO this has nothing
to do with the original issue :) | | | | re: Please confirm this is a MSFT bug
Jake,
Two things:
a) If you think it is a bug, go and register it on the Product Feedback
center. If MS confirms it is a bug, they will put it in their system, if
not, they will tell you why. If you think it ^should^ be addressed, then
you can get votes for your suggestion, and assuming you get enough support,
it will help influence the product.
b) You keep talking about whether or not the compiler conforms to the spec.
The spec is at: http://www.ecma-international.org/pu...T/Ecma-334.pdf
Furthermore, section 12.1.6 of the spec states:
Every output parameter of a function member shall be definitely assigned
(§12.3) before the function member returns normally.
If you then read section 12.3 (as well as re-read what some of the other
posters say), you will eventually see why your code is not legal. The
compiler can not guarantee that Continue will evaulate at ^runtime^ in such
a way that the code path will be hit, and therefore, can not guarantee that
the output variable will be set.
You are asking the compiler to do something which it is not defined (or
required) to do, which is to evaluate ^how^ the code paths will execute,
given all possible values.
There is no need to spam the group, btw, now that you have a) the spec
which you say the compiler should conform to, and b) a way to point out what
you consider to be a bug, and make a suggestion to change the compiler if it
is not (which it is not a bug).
--
- Nicholas Paldino [.NET/C# MVP]
- mvp@spam.guard.caspershouse.com
"Jake Forson" <no_spam@_nospam.com> wrote in message
news:ekrfX2EnGHA.4540@TK2MSFTNGP02.phx.gbl...[color=blue][color=green]
>> Hi,
>>
>> Personally I find the compiler answer correct.
>>
>> It would not happen if you do
>>
>> if (Continue)
>> {
>> Whatever = "Continue";
>> }
>> else
>> Whatever = "Didn't continue";
>>
>>
>> And in any case it's not a bug, it would be more like an optimization[/color]
>
> I don't see how it qualifies as an optimization :) A language is defined
> by a standard which sets down all rules that you must follow. Unless the
> standard stipulates certain rules or conventions that render this example
> illegal (I don't have a copy in front of me to check), then I'm not
> violationg any rules so the compiler is in error :)
>[/color] | | | | re: Please confirm this is a MSFT bug
OK. I never said your example does this. What I am saying is that there
*are* separate, more complex, real-world examples (such as the one I
presented). My key point is that it is highly desirable that the language
and compiler can handle these situations according to a *single*
*consistent* set of rules.
[color=blue]
> If an event fires it will do so on another thread and if that thread is
> going to modify "Continue" in anyway, then someone (the programmer) needs
> to synchronize access to "Continue" using whatever[/color]
Again, from the compiler's perspective they don't *need* to; it is just a
damned good idea. The compiler enforces rules, not ideals. As such the
compiler *cannot* (ever) guard against threading foobars. It's hard enough
for the original developer to identify this!
But... at the end of the day, this whole discussion is a non-issue. It gets
raised on this list (and others) every week or so, and each time the weight
of opinion is with the compiler and the language spec. I will happily
conceed that spec conformance makes a far better reason "why", but IMO the
non-trivial examples like the above help provide counter-cases against what
you are proposing - *particularly* with a view to consistency between
use-cases. It *is* a realistic example; if I could be bothered I would knock
some code together to illustrate. But I can't be ;-p
Marc | | | | re: Please confirm this is a MSFT bug
> There is no need to spam the group, btw, now that you have a) the spec[color=blue]
> which you say the compiler should conform to, and b) a way to point out
> what you consider to be a bug, and make a suggestion to change the
> compiler if it is not (which it is not a bug).[/color]
With all due respect, I'm not spamming this group. Nor do I wish to pursue
this issue ad nauseam. I'm trying to get to the bottom of it. I'm not a
programming novice (20+ years working in C/C++) and I know things aren't
always so cut-and-dry. People make their cases without knowing what the real
rules are and often quote from the standard without understanding it (not
necessarily in your case but in general - there's a lot of technical
legalese to wade through and it's easy to get things wrong). In any case,
now that I have the standard I can check for myself. Don't confuse someone
who's legimately defending a point however with someone who's being hostile
or argumentative (just because it seems that way to you). | | | | re: Please confirm this is a MSFT bug
> See section 12.3.5 of ECMA-334.[color=blue]
>
> http://www.ecma-international.org/pu...T/Ecma-334.pdf
>
> In your case, the compiler wins - it's not required to do the level of
> analysis to prove that the two if statements in your example are mutually
> exclusive, so your two if statements don't constitute definite assignment
> to the variable according to the rules.[/color]
Thanks. I can now look into this myself. Case closed. | | | | re: Please confirm this is a MSFT bug
> OK. I never said your example does this. What I am saying is that there[color=blue]
> *are* separate, more complex, real-world examples (such as the one I
> presented). My key point is that it is highly desirable that the language
> and compiler can handle these situations according to a *single*
> *consistent* set of rules.
>[color=green]
>> If an event fires it will do so on another thread and if that thread is
>> going to modify "Continue" in anyway, then someone (the programmer) needs
>> to synchronize access to "Continue" using whatever[/color]
>
> Again, from the compiler's perspective they don't *need* to; it is just a
> damned good idea. The compiler enforces rules, not ideals. As such the
> compiler *cannot* (ever) guard against threading foobars. It's hard enough
> for the original developer to identify this!
>
> But... at the end of the day, this whole discussion is a non-issue. It
> gets raised on this list (and others) every week or so, and each time the
> weight of opinion is with the compiler and the language spec. I will
> happily conceed that spec conformance makes a far better reason "why", but
> IMO the non-trivial examples like the above help provide counter-cases
> against what you are proposing - *particularly* with a view to consistency
> between use-cases. It *is* a realistic example; if I could be bothered I
> would knock some code together to illustrate. But I can't be ;-p[/color]
Ok, I think we still misunderstand eachother (to some extent) but I
appreciate your input. Thanks again. | | | | re: Please confirm this is a MSFT bug
"Jake Forson" <no_spam@_nospam.com> wrote:
[color=blue]
> Before I notify MSFT, can someone confirm this is in fact a compiler bug (it
> seems pretty obvious but I'm fairly new to C#). The following code
> (erroneously) generates compiler error CS0177 (The out parameter 'Whatever'
> must be assigned to before control leaves the current method).
>
> public void SomeFunc(out string Whatever)
> {
> bool Continue = ShouldWeContinue();
> if (Continue)
> {
> Whatever = "Continue";
> }
>
> if (!Continue)
> {
> Whatever = "Didn't continue";
> }
> }[/color]
The problem is: where do you draw the line about what the compiler
infers from the code? We've got nice predictable rules now that are
solely based on the control-flow primitives and are not based on the
types of values in expressions. I think that's enough, and going down
the route you're suggesting (which is by design and not a bug, BTW)
would create more confusion than it's worth.
-- Barry
-- http://barrkel.blogspot.com/ | | | | re: Please confirm this is a MSFT bug
Jake Forson wrote:[color=blue][color=green]
> > OK. I never said your example does this. What I am saying is that there
> > *are* separate, more complex, real-world examples (such as the one I
> > presented). My key point is that it is highly desirable that the language
> > and compiler can handle these situations according to a *single*
> > *consistent* set of rules.
> >[color=darkred]
> >> If an event fires it will do so on another thread and if that thread is
> >> going to modify "Continue" in anyway, then someone (the programmer) needs
> >> to synchronize access to "Continue" using whatever[/color]
> >
> > Again, from the compiler's perspective they don't *need* to; it is just a
> > damned good idea. The compiler enforces rules, not ideals. As such the
> > compiler *cannot* (ever) guard against threading foobars. It's hard enough
> > for the original developer to identify this!
> >
> > But... at the end of the day, this whole discussion is a non-issue. It
> > gets raised on this list (and others) every week or so, and each time the
> > weight of opinion is with the compiler and the language spec. I will
> > happily conceed that spec conformance makes a far better reason "why", but
> > IMO the non-trivial examples like the above help provide counter-cases
> > against what you are proposing - *particularly* with a view to consistency
> > between use-cases. It *is* a realistic example; if I could be bothered I
> > would knock some code together to illustrate. But I can't be ;-p[/color]
>
> Ok, I think we still misunderstand eachother (to some extent) but I
> appreciate your input. Thanks again.[/color]
Marc's point can be summed up as follows:
If the variable you're testing is local to the method then yes, it
would be possible to determine that the two statements were mutually
exclusive if the compiler were to do that much analysis.
However, if the variable you're testing is a field, part of the
object's state, there is no guarantee that it does not change its value
between the two if statements, and therefore the compiler should
complain that it doesn't know for sure that you have assigned a value
to the "out" parameter.
Nonetheless, I suspect that the real answer is that it's not worth all
of the extra effort and extra code to have the compiler do the level of
analysis needed to determine whether various conditions cover all
possibilities. | | | | re: Please confirm this is a MSFT bug
Jake Forson <no_spam@_nospam.com> wrote:[color=blue]
> Thanks for the info. While the KISS principle may apply here (on that we
> agree), I'm at odds with your other points. It's certainly easier to parse
> code without worrying about trapping this type of scenario and even
> beneficial if it imrpoves compiler performance and robustness, but it's
> still legal IMO (or should be). I doubt the C# standard says otherwise (I'd
> be surprised to find out).[/color]
The C# standards are very clear on definite assignment, and they don't
contain any rules about the compiler performing any logic to determine
that one of two paths through code must be taken.
--
Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too | | | | re: Please confirm this is a MSFT bug
Jake Forson wrote:[color=blue]
> With all due respect, I'm not spamming this group. Nor do I wish to pursue
> this issue ad nauseam. I'm trying to get to the bottom of it. I'm not a
> programming novice (20+ years working in C/C++) and I know things aren't
> always so cut-and-dry. People make their cases without knowing what the real
> rules are and often quote from the standard without understanding it (not
> necessarily in your case but in general - there's a lot of technical
> legalese to wade through and it's easy to get things wrong). In any case,
> now that I have the standard I can check for myself. Don't confuse someone
> who's legimately defending a point however with someone who's being hostile
> or argumentative (just because it seems that way to you).[/color]
Jake, you said multiple times in this thread that it's the spec that
matters, not the language. Yet you never checked the spec, just
assumed that the compiler must be in error. That's why you're getting
this heat.
The standard's online (and on the first page of a Google "c# spec"
search. They'll even send you hard copies for free). It's not that
hard to read - why didn't you check it before (repeatedly) calling the
compiler non-compliant against that spec? | | | | re: Please confirm this is a MSFT bug
I disagree that this is the situation. Your real-world example is definitely
a very good example of why the compiler should catch this as it has done,
but I really don't believe that it's that smart.
I think it boils down to something like this ..
object DoSomething(ref out object obj) {
bool cond = true;
if (cond) { // compiler sees a condition
obj = true;
} // no else statement; set value to obj ignored
if (false) { // compiler sees a condition
obj = false;
} // no else statement; set value to obj ignored
}
object DoSomething(ref out object obj) {
bool cond = true;
if (cond) { // compiler sees a condition
obj = true; // check; double-check in else statement required
} else {
obj = false; // double-check; set value to obj recognized
}
}
Jon
"Marc Gravell" <marc.gravell@gmail.comwrote in message
news:OV0UddEnGHA.1244@TK2MSFTNGP05.phx.gbl... Quote:
As written, yes - we can observe that it will always have a value by the
time it exits.
>
However: if the variable was a field, or if the variable was used in a
(2.0) anonymous delegate (as a /captured/ variable), then it would be
possible for (without it being obvious in the code) another thread to
alter the value of Continue between the two calls, which incidentally may
or may-not be spotted depending on volatility / memory-barriers. Given
this, it makes a lot of sense for me for the compiler to follow the "keep
it simple" principle, and consider all three cases equally - otherwise you
would have to remember daft rules about when each applies, and making a
change (like using it in an anonymous delegate) would suddenly cause
unrelated code to not compile.
>
Does that make sense?
>
Marc
>
| | | | re: Please confirm this is a MSFT bug
Same principle applies to ..
enum enm {
a, b
}
bool DoSomethingElse(enm someEnum) {
switch (someEnum) { // someEnum can only be enm.a or enm.b
case enm.a:
return true;
case enm.b:
return false;
}
}
This will not compile. However, this will.
enum enm {
a, b
}
bool DoSomethingElse(enm someEnum) {
switch (someEnum) { // someEnum can only be enm.a or enm.b
case enm.a:
return true;
case enm.b:
default: <<<<< compiler will always set something
return false;
}
}
"Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.netwrote in message
news:O73QOLbnGHA.3440@TK2MSFTNGP04.phx.gbl... Quote:
>I disagree that this is the situation. Your real-world example is
>definitely a very good example of why the compiler should catch this as it
>has done, but I really don't believe that it's that smart.
>
I think it boils down to something like this ..
>
object DoSomething(ref out object obj) {
bool cond = true;
if (cond) { // compiler sees a condition
obj = true;
} // no else statement; set value to obj ignored
>
if (false) { // compiler sees a condition
obj = false;
} // no else statement; set value to obj ignored
}
>
object DoSomething(ref out object obj) {
bool cond = true;
if (cond) { // compiler sees a condition
obj = true; // check; double-check in else statement required
} else {
obj = false; // double-check; set value to obj recognized
}
}
>
Jon
>
>
"Marc Gravell" <marc.gravell@gmail.comwrote in message
news:OV0UddEnGHA.1244@TK2MSFTNGP05.phx.gbl... Quote:
>As written, yes - we can observe that it will always have a value by the
>time it exits.
>>
>However: if the variable was a field, or if the variable was used in a
>(2.0) anonymous delegate (as a /captured/ variable), then it would be
>possible for (without it being obvious in the code) another thread to
>alter the value of Continue between the two calls, which incidentally may
>or may-not be spotted depending on volatility / memory-barriers. Given
>this, it makes a lot of sense for me for the compiler to follow the "keep
>it simple" principle, and consider all three cases equally - otherwise
>you would have to remember daft rules about when each applies, and making
>a change (like using it in an anonymous delegate) would suddenly cause
>unrelated code to not compile.
>>
>Does that make sense?
>>
>Marc
>>
>
>
| | | | re: Please confirm this is a MSFT bug
"Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.netwrote: Quote:
Same principle applies to ..
>
enum enm {
a, b
}
The principle is actually quite different for enumerations. A bool
expression will always either evaluate to true or false, since (under
the CLI) it's based on integers being zero or non-zero. Quote:
bool DoSomethingElse(enm someEnum) {
switch (someEnum) { // someEnum can only be enm.a or enm.b
This statement is where it falls apart. The enumeration value "(enm) 3"
will fit into a variable of type enm without error, so it isn't true
that someEnum can only be enm.a or enm.b.
-- Barry
-- http://barrkel.blogspot.com/ | | | | re: Please confirm this is a MSFT bug
"Barry Kelly" <barry.j.kelly@gmail.comwrote in message
news:2k5fa2tj418dvtt2k96d0tuturjm9dbb9n@4ax.com... Quote:
This statement is where it falls apart. The enumeration value "(enm) 3"
will fit into a variable of type enm without error, so it isn't true
that someEnum can only be enm.a or enm.b.
Fine, ignore the commented portion, I was just trying to paint a scenario. I
was demonstrating the switch requiring a default value, not the enum, a
point that is retained regardless of (enm)3.
Try pasting the sample into VS or SnippetCompiler and you'll see the same
error.
'MyClass.DoSomethingElse(MyClass.enm)': not all code paths return a value
Jon | | | | re: Please confirm this is a MSFT bug
Jon Davis <jon@REMOVE.ME.PLEASE.jondavis.netwrote: Quote:
"Barry Kelly" <barry.j.kelly@gmail.comwrote in message
news:2k5fa2tj418dvtt2k96d0tuturjm9dbb9n@4ax.com... Quote:
This statement is where it falls apart. The enumeration value "(enm) 3"
will fit into a variable of type enm without error, so it isn't true
that someEnum can only be enm.a or enm.b.
>
Fine, ignore the commented portion, I was just trying to paint a scenario. I
was demonstrating the switch requiring a default value, not the enum, a
point that is retained regardless of (enm)3.
>
Try pasting the sample into VS or SnippetCompiler and you'll see the same
error.
>
'MyClass.DoSomethingElse(MyClass.enm)': not all code paths return a value
And it's absolutely right - if you pass in (enm)3 as the parameter,
then without the default case, your code would reach the end of the
method without returning anything. It's absolutely correct for the
compiler to complain about that.
It's not that switch requires a default, it's a matter of the
reachability of the end of the switch statement.
Now, the C# spec states:
<quote>
The end point of a switch statement is reachable if at least one of the
following is true:
* The switch statement contains a reachable break statement that
exits the switch statement.
* The switch statement is reachable, the switch expression is a
non-constant value, and no default label is present.
* The switch statement is reachable, the switch expression is a
constant value that doesn=3Ft match any case label, and no default label
is present.
</quote>
This is only actually conservative if the switch expression is a non-
constant value and you specify *every* value in the appropriate type as
a case label. For instance, if you were switching on a byte and all 256
possible values were specified and all of them returned, you'd still
have to have a default case. I can't remember ever seeing such a
situation, personally - so simplicity on the part of spec is
reasonable.
--
Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too |  | Similar C# / C Sharp bytes | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,295 network members.
|