IanPudney
IanPudney

Reputation: 6041

Programmatically get cast and output Types of operator

In C#, given two input Types, it it possible to determine the output Type and implicit upcast Types for an operator? For example, consider the expression s + i. Say I have the following information:

short s;
int i;
Type leftType = typeof(short);
Type rightType = typeof(int);

Can I determine the following information about the expression s + i?

Type leftUpcastType = typeof(int);
Type rightUpcastType = typeof(int);
Type outputType = typeof(int);

I obviously could do this with an enormous lookup table of all the types and operators, but there might be an easier way. Ideally this would work for user-defined classes with operator overloads too, but that is a secondary requirement.

Upvotes: 3

Views: 158

Answers (2)

user1726343
user1726343

Reputation:

The best way to do this is to examine the return type of an expression that adds two values of the types you're interested in. This way you don't need to worry about providing valid values for the addition at runtime, when all you care about is the return type.

You can either take an existing expression and walk down the expression tree if one is available to you, or do something like this:

static Type GetTypeOfSummation<T1, T2>()
{
    var p1 = Expression.Parameter(typeof(T1), "t1");
    var p2 = Expression.Parameter(typeof(T2), "t2");

    LambdaExpression x = DynamicExpression.ParseLambda(new[] { p1, p2 }, null, "t1 + t2");
    return x.Body.Type;
}

static void Main()
{
    Console.WriteLine(GetTypeOfSummation<int, double>());   // System.Double
    Console.WriteLine(GetTypeOfSummation<int, decimal>());  // System.Decimal
    Console.WriteLine(GetTypeOfSummation<float, double>()); // System.Double
}

This generic method will return the type of the addition operation without actually performing the addition.

You can of course do this with Type instances instead of generic type parameters as well, if that's what you want:

static Type GetTypeOfSummation(Type t1, Type t2)
{
    var p1 = Expression.Parameter(t1, "t1");
    var p2 = Expression.Parameter(t2, "t2");

    LambdaExpression x = DynamicExpression.ParseLambda(new[] { p1, p2 }, null, "t1 + t2");
    return x.Body.Type;
}

To be clear, DynamicExpression is from the System.Linq.Dynamic namespace, which you can obtain by referencing: https://www.nuget.org/packages/System.Linq.Dynamic/

Upvotes: 2

Steve Lillis
Steve Lillis

Reputation: 3256

Yes, you can achieve this using the dynamic Type. Keep in mind, though, that dynamic will throw an exception for anything that can't be summed at runtime so you will need to ensure that you are only passing valid values or wrap in a try/catch.

var leftType = left.GetType();
var rightType = right.GetType();
var outputType = ((dynamic)left + (dynamic)right).GetType();

You can then infer from this information whether one, both or neither of the objects were converted for the operation.

Upvotes: 2

Related Questions