I'm trying to come up with a function to determine the result type of arithmetic operations, say for the case of addition:
Type TypeOfAddition(Type leftType, Type rightType)
{
// ???
}
Type TypeOfMultiplication(Type leftType, Type rightType)
{
// ???
}
// ... same for subtraction and division
These desired result of these functions is probably clear; Essentially, my goal is do to the same (at runtime) that Visual Studio does when inferring types to "var"-type variables when doing arithmetic operations.
For example,
public class MyClass
{
public static string operator +(MyClass left, double right)
{
// ...
}
}
TypeOfAddition(typeof(int), typeof(double)); // Should return typeof(double)
TypeOfAddition(typeof(string), typeof(int)); // Should return typeof(string)
TypeOfAddition(typeof(MyClass), typeof(double)); // Should return typeof(string)
My base idea was an implementation like, conceptually
Type TypeOfAddition(Type leftType, Type rightType)
{
return leftType.GetMethods().Single(x =>
x.Name == "op_Addition" &&
x.GetParamters().Count == 2 &&
x.GetParameters().Last().ParameterType == rightType);
}
but
A) This won't work for base types like int, double etc., which don't seem to explicitly define operator overloads, and
B) The above linq clause won't catch all cases yet (e.g. inheritance)
I could hard-code the base types and try to come up with a smart solution for B) as well, but that seems relatively .. unelegant.
Is there any smarter / easier / good solution to solving this? Mind you, I only want to get the theoretical type of the result of such an operation, without actually executing an arithmetic operation explicitly.
Thanks!
It certainly isn't pretty, and definitely isn't fast, but it appears to work with the basic tests I've ran it through.
Note that you'll need to have
Microsoft.CSharp.dll
referenced.Example outputs:
This uses what Jeroen mentioned in the comments (RuntimeBinder) to create a addition binder. It then builds a dynamic expression tree to add the default values of both
TLeft
andTRight
. I had to add a small function calledGetDefault
to resolvestring
to an empty string, since I'm assuming you want to seestring
when trying to add"" + 0
instead ofnull
. If you do want to see nulls, just replace theGetDefault
calls withdefault(TLeft)
anddefault(TRight)
.It doesn't call constructors (due to using
GetUninitializedObject
) contains a special case for strings.There are likely many possible improvements, and I am all ears.
Maybe you could try Generics in your methods. Something like
Using Roslyn, I now came up with the following. So far from what I tested, it seems to work fine - let me know what you think.
Downsides (no major issue in my case though) from what I see are
Obviously need to use/deploy a lot of Roslyn assemblies with my app just for this
with usage just being