Skip to content

API Proposal: Type.IsAssignableTo(Type) #30714

Closed
mono/mono
#20206
@benaadams

Description

@benaadams

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.
}

/cc @NickCraver @davkean @davidfowl

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions