Closed
Description
Background
The api Type.IsAssignableFrom(Type)
is quite common to mistakenly use backwards because it flows unexpectedly with surrounding code (swapping the subject and object; the type you are interested in becoming a parameter rather than staying as the caller).
Proposal
To alleviate this introducing a reversal of the parameters either as extension or method would be helpful to differentiate and provide clarity:
partial class Type
{
public bool Type.IsAssignableTo(Type type)
=> type.IsAssignableFrom(this);
public static bool IsAssignableTo<T>()
=> typeof(T).IsAssignableFrom(this);
}
or
partial static class TypeExtensions
{
public static bool Type.IsAssignableTo(this Type type, Type assignableType)
=> assignableType.IsAssignableFrom(type);
public static bool IsAssignableTo<T>(this Type type)
=> typeof(T).IsAssignableFrom(type);
}
Precedence
Type.IsSubclassOf(Type)
works in this direction so currently the syntax is
typeof(derived).IsSubclassOf(typeof(base));
typeof(base).IsAssignableFrom(typeof(derived)); // swapped subject object
typeof(IInterface).IsAssignableFrom(typeof(Implementation)); // swapped subject object
While reversing
typeof(derived).IsSubclassOf(typeof(base));
typeof(derived).IsAssignableTo(typeof(base));
typeof(Implementation).IsAssignableTo(typeof(IInterface));
Example usage
Given
public class ConstrainedGeneric<T> where T : Stream
{}
Rather than writing
public static void Main()
{
Type genericT = typeof(ConstrainedGeneric<>);
Type genericParam = genericT.GetGenericArguments()[0];
if (typeof(Stream).IsAssignableFrom(genericParam))
{
Console.WriteLine(true);
}
// Displays True.
}
You can write
public static void Main()
{
Type genericT = typeof(ConstrainedGeneric<>);
Type genericParam = genericT.GetGenericArguments()[0];
if (genericParam.IsAssignableTo(typeof(Stream)))
{
Console.WriteLine(true);
}
// Displays True.
}