Compiler error found...

?

-

Hi to All,

To reproduce:

The expression:

object result = flag ? (long) 0 : (double) 0;
always evaluated as a double... see dissassembly to ensure the bad compiled
code.

Just for sure:

if (flag) {
result = (long) 0;
}
else {
result = (double) 0;
}

works correctly. The <? :> operator should be _equivalent_

PS: This is .NETFX 1.1 whith VS.NET 2003, XP Prof SP2.

Very disappointing...
 
L

Larry Brasfield

- said:
Hi to All,
Hello Mr./Ms. -.
To reproduce:

The expression:

object result = flag ? (long) 0 : (double) 0;
always evaluated as a double... see dissassembly to ensure the bad compiled code.

If you study the online docs for the C# conditional operator, at:
ms-help://MS.MSDNQTR.2003FEB.1033/csspec/html/vclrfcsharpspec_7_12.htm
you will find language like this:
<quote>
The second and third operands of the ?: operator control the type of the conditional
expression. Let X and Y be the types of the second and third operands. Then,
* Iff X and Y are the same type, then this is the type of the conditional expression.
* Otherwise, if an implicit conversion (Section 6.1) exists from X to Y, but not from
Y to X, then Y is the type of the conditional expression.
* Otherwise, if an implicit conversion (Section 6.1) exists from Y to X, but not from
X to Y, then X is the type of the conditional expression.
Just for sure:

if (flag) {
result = (long) 0;
}
else {
result = (double) 0;
}

works correctly. The <? :> operator should be _equivalent_

No, it should behave as the language spec requires. It is
only in your own mind that there should be such equivalence.
PS: This is .NETFX 1.1 whith VS.NET 2003, XP Prof SP2.

Very disappointing...

You must be dissappointed often if youu are unwilling to
read the spec when a compiler does not act as you hope.
 
J

Jon Skeet [C# MVP]

- said:
Hi to All,

To reproduce:

The expression:

object result = flag ? (long) 0 : (double) 0;
always evaluated as a double... see dissassembly to ensure the bad compiled
code.

Yup, the type of the result expression of the conditional operator is
always the same.
Just for sure:

if (flag) {
result = (long) 0;
}
else {
result = (double) 0;
}

works correctly. The <? :> operator should be _equivalent_

No it shouldn't. See section 14.12 of the ECMA C# language spec for
exactly what happens. In this case, there's an implicit conversion from
long to double, so that's the type of the resulting expression. Look at
the bottom paragraph of the section, talking about the run-time
processing of the conditional expresssion - particularly where it says
"x is evaluated and converted to the type of the conditional
expression, and this becomes the result of the conditional expression".
PS: This is .NETFX 1.1 whith VS.NET 2003, XP Prof SP2.

Very disappointing...

Nope, just not what you expected.
 
N

Nick Malik [Microsoft]

this from a person who didn't sign their name.

RTFM

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
 
?

-

Hi Jon and Larry (I reply here once for both of yours)

First of all, thx for your feedback, and I have to say you are completly
rigth, I was wrong.
The compiler behaves as expected by lang. spec..

Conclusion:

The ? : operator can not be used in polimorphic way. For example we can not
write:

Fruit myFruit = flag ? new Lime() : new Orange();

The question is: What was the Architect reason to disable this?

Lang spec expects Orange to be type compatible (can implicitly cast) to
Lime. This is a logic mistake, and very poor interpetation of
polimorhism. Both Lime and Orange must be compatible with left side, but not
with each other, because programmer never wanted to convert them to each
other, Then why the language spec want to do?

In logic term:
<lvalue> = <exp1> ?<exp2>?<exp3>

<exp2> compatible whith <lvalue> .And. <exp3> compatible whith <lvalue> does
not .Implicates. that <exp3> compatible with <exp2>.

Again thx for your corrections.
 
?

-

Hi Nick,

First of all: regarding RTFM you was completly right, see my answer to
others.

Secondly:

If I remember correctly I never offended any _person_ here by qualifiyng his
/ her behaviour
so please as a mutual act do not qualify me regarding you are right or not.

We should all rethink this:
There are two groups of people: Who divides people two groups and who don't.
:)
(watch for recursion!)

-
 
J

Jon Skeet [C# MVP]

- said:
Hi Jon and Larry (I reply here once for both of yours)

First of all, thx for your feedback, and I have to say you are completly
rigth, I was wrong.
The compiler behaves as expected by lang. spec..

Conclusion:

The ? : operator can not be used in polimorphic way. For example we can not
write:

Fruit myFruit = flag ? new Lime() : new Orange();

The question is: What was the Architect reason to disable this?

Lang spec expects Orange to be type compatible (can implicitly cast) to
Lime. This is a logic mistake, and very poor interpetation of
polimorhism. Both Lime and Orange must be compatible with left side, but not
with each other, because programmer never wanted to convert them to each
other, Then why the language spec want to do?

I believe it's so that each expression has a type associated with it
which is independent of the use of the expression.
 
L

Larry Brasfield

[Top-posting undone for clarity.]

- said:
Hi Jon and Larry (I reply here once for both of yours)

First of all, thx for your feedback, and I have to say you are completly rigth, I was wrong.

Your willingness to go there encourages me to explain
why it works that way, below. I am going to expand
upon Jon's answer in an attempt to give a glimpse into
the reason type deduction should flow from leaves of
a parse tree toward its root.
The compiler behaves as expected by lang. spec..

Conclusion:

The ? : operator can not be used in polimorphic way. For example we can not write:

Fruit myFruit = flag ? new Lime() : new Orange();

But you can use a typecast to express your intent:
Fruit myFruit = flag ? (new Lime() as Fruit) : (new Orange() as Fruit);
Not as convenient, but as we will see, necessary.
The question is: What was the Architect reason to disable this?

Lang spec expects Orange to be type compatible (can implicitly cast) to Lime. This is a logic mistake, and very poor interpetation
of
polimorhism. Both Lime and Orange must be compatible with left side, but not with each other, because programmer never wanted to
convert them to each other, Then why the language spec want to do?

In logic term:
<lvalue> = <exp1> ?<exp2>?<exp3>

<exp2> compatible whith <lvalue> .And. <exp3> compatible whith <lvalue> does not .Implicates. that <exp3> compatible with <exp2>.

First, I will agree that for the simple example you show,
it seems reasonable that the type of <lvalue> would
participate in the sematic analysis of the conditional
expression. But it is the head of a trail to madness.

The situation now, as the C# language (and every other
strongly typed programming language I that know) is
designed, the type of an expression can be deduced
from its immediate subexpressions. This situation is
amenable to the semantic analysis that is needed both
to produce executable code and to permit people to
understand what their constructs mean.

To accommodate your expectation/criticism, it would
be necessary to have an additional or replacement
rule, where the type of subexpressions may be deduced
from the use to which its result will be put.

Making the reverse deduction rule an addition to the
current rule leads to some nasty conundrums. Where
in a parse tree should from-root-toward-leaf deduction
stop and from-leaf-toward-root deduction begin? For
your simple expression, where there is only a single
assignment at the root of the parse tree, the answer is
clear: Type deduction should flow up (toward the root)
from the LHS then down into the conditional expression
and hence down into the conditional's leaves. But what is
the rule that will govern more complex parse trees? Will
you make a special case for the assignment operator?
Consider a conditional expression used as an argument
to a function overloaded on that same parameter position.
Now there is more than one type that should flow down
into the conditional expression.

You could eliminate the problem with deciding where
type deduction changes direction by replacing the
current rule entirely. Even more madness lies down
that trail. If the rule is that type deduction always flows
from the root toward the leaves, it is possible to make
compilers follow it provided they apply a backtracking
algorithm to the task and more rules to disambiguate
the (possible) multiple choices implied by the need to
backtrack. This might lead to only some of the compiler
implementers and language designers being carried away
in straight-jackets, but the toll among language users will
be heavier. This is because they must (or should, if they
are concientious) understand what their code means. By
the time you have code difficult for a compiler designer
to handle, it is practially impossible for plain humans to
understand without the use of a computer.
Again thx for your corrections.
You're welcome.
 
?

-

Hi Larry,

Thx for your detailed answer and time,

Things are always more complicated as they seems at first sight.
It's a bit scary that "behavior why s" of a simple operator <? :> can lead
to this deep understandings.
Then how about "reentrancy of static constructors in multithreaded env." or
"enterprise applications" etc.

Anyway, this was very learnfull.

Thx again.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top