type of expression in C# 2.0?

B

bob_jenkins

In C# 2.0, given an arbitrary expression and the types of the
variables referenced in it, how do I find the expression type? For
example,
int x;
float y;
what is the type of x+y?

If I had values for x and y, I could do (x+y).GetType(). But I don't,
I just have their types. Default values won't work because values
that don't cause the expression to raise an error might be very hard
to come by.

I can dynamically generate
public static object f(int x, float y)
{
object o = x+y;
return o;
}
and use reflection (MethodInfo->MethodBody->LocalVariables) to find
that o is of type System.Object, and I'll get a typecheck error if x+y
isn't allowed, but I don't see how to get the type of x+y given that
it is allowed. If I had C# 3.0, I think I could do "var o = x+y;"
then use reflection to find the type of o, but I've only got C# 2.0.

It's conceivable that x+y returns different types depending on the
values of x and y, so x+y truly has no type.
 
C

Chris Mullins [MVP - C#]

I just read an incredible chapter in a forthcoming C# book on Lamba
Expressions and Expression Trees.

What you describe is, from what I understand, almost exact how the compiler
would build an expression tree. I don't think, in C# 2.0, the tools exist
for you to do it.

Hopefully the author of that book will chime in with the real answer soon,
and we'll all become a bit more educated...
 
J

Jesse Houwing

Hello (e-mail address removed),
In C# 2.0, given an arbitrary expression and the types of the
variables referenced in it, how do I find the expression type? For
example,
int x;
float y;
what is the type of x+y?
If I had values for x and y, I could do (x+y).GetType(). But I don't,
I just have their types. Default values won't work because values
that don't cause the expression to raise an error might be very hard
to come by.

I can dynamically generate
public static object f(int x, float y)
{
object o = x+y;
return o;
}
and use reflection (MethodInfo->MethodBody->LocalVariables) to find
that o is of type System.Object, and I'll get a typecheck error if x+y
isn't allowed, but I don't see how to get the type of x+y given that
it is allowed. If I had C# 3.0, I think I could do "var o = x+y;"
then use reflection to find the type of o, but I've only got C# 2.0.

It's conceivable that x+y returns different types depending on the
values of x and y, so x+y truly has no type.

The expression will always return the same type if the same types of x and
y are used. The only difference can be found if
a) another version of the compiler is used (subtle differences exist between
pre 2.0 and post 2.0 versions of the framework)
b) the language beign compiled (java uses different rules then c# for example)

The rules that decide the type only look at the type of both operands. The
value will never be considered. So int/decimal will always result in a decimal.


A bit of information can be found in the C# Language reference, but it isn't
entirely clear.

The followin automatic conversions are possible. If the two types are different,
the compiler will choose to convert either one, or both of the types to the
nearest possible type in order to do the requested action:

The implicit numeric conversions are:
• From sbyte to short, int, long, float, double, or decimal.
• From byte to short, ushort, int, uint, long, ulong, float, double, or
decimal.
• From short to int, long, float, double, or decimal.
• From ushort to int, uint, long, ulong, float, double, or decimal.
• From int to long, float, double, or decimal.
• From uint to long, ulong, float, double, or decimal.
• From long to float, double, or decimal.
• From ulong to float, double, or decimal.
• From char to ushort, int, uint, long, ulong, float, double, or decimal.
• From float to double

You can find the original spec here:
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

With this information it should be possible to write a small helper function
that will deduct the information you need. Though that will ignore custom
conversion functions, custom types etc.
 
J

Jon Skeet [C# MVP]

Chris Mullins said:
I just read an incredible chapter in a forthcoming C# book on Lamba
Expressions and Expression Trees.

What you describe is, from what I understand, almost exact how the compiler
would build an expression tree. I don't think, in C# 2.0, the tools exist
for you to do it.

Hopefully the author of that book will chime in with the real answer soon,
and we'll all become a bit more educated...

I wish :)

The way the compiler works it out is by knowing the various addition
operations available, e.g.

int op_Addition(int x, int y)
long op_Addition(long x, long y)
double op_Addition(double x, double y)
float op_Addition(float x, float y)

(etc)

It then applies normal overload resolution. The first two of the above
overloads isn't valid, but the bottom two are, having performed
implicit conversions. The conversion from float to float is better than
from float to double, and the conversion from int to float is as good
as the conversion from int to double, so the bottom overload is used.

But basically you need to have this information available to you...
 
J

Jon Skeet [C# MVP]

It's conceivable that x+y returns different types depending on the
values of x and y, so x+y truly has no type.

No, if x+y are variables, x+y will always have the same type,
determined at compile time.
 
B

bob_jenkins

Hello (e-mail address removed),






The expression will always return the same type if the same types of x and
y are used. The only difference can be found if
a) another version of the compiler is used (subtle differences exist between
pre 2.0 and post 2.0 versions of the framework)
b) the language beign compiled (java uses different rules then c# for example)

The rules that decide the type only look at the type of both operands. The
value will never be considered. So int/decimal will always result in a decimal.

A bit of information can be found in the C# Language reference, but it isn't
entirely clear.

The followin automatic conversions are possible. If the two types are different,
the compiler will choose to convert either one, or both of the types to the
nearest possible type in order to do the requested action:

The implicit numeric conversions are:
· From sbyte to short, int, long, float, double, or decimal.
· From byte to short, ushort, int, uint, long, ulong, float, double, or
decimal.
· From short to int, long, float, double, or decimal.
· From ushort to int, uint, long, ulong, float, double, or decimal.
· From int to long, float, double, or decimal.
· From uint to long, ulong, float, double, or decimal.
· From long to float, double, or decimal.
· From ulong to float, double, or decimal.
· From char to ushort, int, uint, long, ulong, float, double, or decimal.
· From float to double

You can find the original spec here:http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334...

With this information it should be possible to write a small helper function
that will deduct the information you need. Though that will ignore custom
conversion functions, custom types etc.

Could I do this without writing my own C# parser to parse the
expression?
 

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