I have this:
var newFoo = new Foo<Car>();
DoSomething(newFoo);
void DoSomething(Foo inputFoo)
{
if (inputFoo is Foo<IDrivable> f) Console.WriteLine("It is a Foo<IDrivable>.");
else Console.WriteLine("Nope, not a Foo<IDrivable>.");
}
public abstract class Foo { }
public class Foo<T>:Foo { }
public interface IDrivable { }
public class Car : IDrivable { }
This prints "Nope, not a Foo<IDrivable>"
.
Is it possible to perform a contravariant check on T
somehow? How do I refactor the above to print "It is a Foo<IDrivable>"
given a Foo<Car>
?
CodePudding user response:
You can check whether there is a generic parameter and whether (the first one) is assignable to IDrivable
.
var firstTypeParameter = inputFoo.GetType().GenericTypeArguments.FirstOrDefault();
if (firstTypeParameter != null && firstTypeParameter.IsAssignableTo(typeof(IDrivable)))
Console.WriteLine("It is a Foo<IDrivable>");
Edit:
As noted in a comment, a more elegant solution can be achieved if you're willing to introduce another interface:
public interface IFoo<out T> { }
public class Foo<T> : Foo, IFoo<T> { }
The check then becomes
if (inputFoo is IFoo<IDrivable> f)
Console.WriteLine("It is a Foo<IDrivable>.");
CodePudding user response:
var newFoo = new Foo<Car>();
DoSomething(newFoo);
void DoSomething(Foo inputFoo)
{
if (inputFoo.GetType().GetGenericTypeDefinition() == typeof(Foo<>) && typeof(IDrivable).IsAssignableFrom(inputFoo.GetType().GetGenericArguments()[0])) Console.WriteLine("It is a Foo<IDrivable>.");
else Console.WriteLine("Nope, not a Foo<IDrivable>.");
}
public abstract class Foo { }
public class Foo<T>:Foo { }
public interface IDrivable { }
public class Car : IDrivable { }