0

I have two System.Type objects, say, a and b. I need a way to know whether the type represented by a can be casted to the type represented by b. For instance, if:

a = typeof(int)
b = typeof(double)

An int can be casted to a double , so the condition would be true.

I considered a.IsAssignableTo(b), but that only detects if either a == b or a is descended from b, not if a user-defined conversion exists.

Any suggestions would be greatly appreciated.

Bear in mind that have only the System.Type objects for the two types, no instances or generic type parameters. This is not a duplicate of other questions where they already have instances of the type in question, such as How to check if type can be converted to another type in C#.

256Bits
  • 378
  • 1
  • 13
  • 1
    Casts between these types are actually *type conversions* that are handled by the compiler. There's no runtime information available. – madreflection Aug 17 '23 at 15:29
  • Maybe elaborate a little what problem your are trying to solve with that. My impression is, that this may be an x-y Question. – Fildor Aug 17 '23 at 15:59
  • Perhaps `is`, `as`, and `typeof` could help: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast#is-operator – Ibrennan208 Aug 17 '23 at 16:09
  • @Ibrennan208 The article you provided contains a way to test weather a variable can be casted to a type. I need a way to test weather any variable of the type represented by the Type object can be casted to the type represented by another Type object. – 256Bits Aug 17 '23 at 16:12
  • Does this answer your question? [How to check if type can be converted to another type in C#](https://stackoverflow.com/questions/17676838/how-to-check-if-type-can-be-converted-to-another-type-in-c-sharp) – Heretic Monkey Aug 17 '23 at 16:38
  • @HereticMonkey No. In that question, they already have a variable of that type. I have no instances of either type, only the ```System.Type``` objects. – 256Bits Aug 17 '23 at 19:35
  • The question, post-clarification, looks for an implementation of a method `MatchResultTypeAndExpectedType(Type sourceType, Type targetType)` which, to my eye, does not have any instances of any Types... Indeed, the first requirement of its specification is "Source and target types are not known at compile time, since their assemblies are loaded later." – Heretic Monkey Aug 17 '23 at 21:37
  • Also see https://stackoverflow.com/questions/32025201/how-can-i-determine-if-an-implicit-cast-exists-in-c - you have to explicitly check for primitive type conversions. – Matthew Watson Aug 18 '23 at 08:17

2 Answers2

0

You can do it by testing it. If you have no instance of the types, you might create a default instance using Activator.

The assignment test can be handled through some MakeGenericType / MakeGenericMethod reflection magic.

As for the int to double (OK) and double to int (NOK) example, this shows how to do it (See also on netfiddle https://dotnetfiddle.net/1MBNxg ):

using System;
                    
public class Program
{
    public static void Assign<T>(T value) {}
    
    public static void Main()
    {
        AssignmentTest(typeof(int), typeof(double));
        /* Output:
           FAILURE: CANNOT assign Double to Int32
           SUCCESS: CAN assign Int32 to Double             */
    }
    
    static (bool, bool) AssignmentTest(Type t1, Type t2)
    {
        var xObj = Activator.CreateInstance(t1);
        var yObj = Activator.CreateInstance(t2);        
    
        var assignGenMethod = typeof(Program).GetMethod(nameof(Assign));
    
        var xAssignMethod = assignGenMethod.MakeGenericMethod(xObj.GetType());
        var yAssignMethod = assignGenMethod.MakeGenericMethod(yObj.GetType());
    
        return (
          InvokeSafe(xAssignMethod, yObj),
          InvokeSafe(yAssignMethod, xObj)
        );
    }
    static bool InvokeSafe(MethodInfo method, object value)
    {
        try
        {
            method.Invoke(null, new []{ value} );
            Console.WriteLine("SUCCESS: CAN assign {0} to {1}", value.GetType().Name, method.GetParameters()[0].ParameterType.Name);
            return true;
        }
        catch
        {   
            Console.WriteLine("FAILURE: CANNOT assign {0} to {1}", value.GetType().Name, method.GetParameters()[0].ParameterType.Name);
            return false;
        }
    }
}
lidqy
  • 1,891
  • 1
  • 9
  • 11
-3

In .NET, the Type.IsAssignableFrom method can be used to check whether a given type is assignable to a particular type. This method checks whether it is possible to convert from the type sent as a parameter to the type represented by the object.

In your code example:


Type a = typeof(int);
Type b = typeof(double);

bool isAssignable = b.IsAssignableFrom(a);
Console.WriteLine(isAssignable); // will return true

In this example, the program will print true, since type double can contain values of type int.

I recommend formulating the condition in the opposite way, that is to check whether type a can be assigned to type b, because the assignment from a large type to a small type may result in a loss of information:

bool isAssignable = a.IsAssignableFrom(b);

Note that the IsAssignableFrom method is associated with an object of type Type and not with types directly.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
MALI
  • 1
  • 1