7

What's the difference between:

typeof(IInterface).IsAssignableFrom(typeof(Class));

and

typeof(Class) is IInterface

?

Edit: for context, my function is something like this:

public static List<T> GetAllInstancesOfType<T>() where T:Entity
{
  List<T> l = new List<T>();

  if (typeof(IMyInterface).IsAssignableFrom(typeof(T)) //or (typeof(T) is IMyInterface)
     foreach(Entity e in List1) if (e is T) l.Add(e as T);

  else foreach (Entity e in List2) if (e is T) l.Add(e as T);

  return l;
}
Haighstrom
  • 577
  • 5
  • 16

3 Answers3

14

They are similar-looking but conceptually very different. The former answers the question "if I had a variable of this type, could I assign to it a value of that type?"

The latter answers the question "can this actual value be converted to this type via reference or boxing conversion?"

In the latter case, the actual object is an object of type Type, not an object of type Class. Make sure you understand the difference between:

Type t = typeof(Class);
Class c = new Class();
bool b1 = t is IInterface;
bool b2 = c is IInterface;

The first asks "can the Type object be converted to the interface?" and the second asks "can the Class object be converted to the interface?"

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • I'm writing a GetAllInstancesOfType() style function, and inferring information of which list to look in for Ts from the interface T implements (i.e. if T does implement interface I look in list A, if not look in list B). Since all I'm checking is "does T implement I", from your answer I'm talking about whether a variable T could be assigned a value of type I, and not conversion from I to T - and therefore I should use option 1? – Haighstrom Jul 18 '13 at 14:55
  • @Haighstrom: I don't understand your scenario well enough to make a recommendation, but something seems strange about it. If you want to know if a given `Type` represents a type that implements a particular interface then why on earth are you checking for *variable assignability*? What do variables have to do with it? If you want to know if a type implements an interface then just ask the type for a list of its implemented interfaces! Remember, *assignability* and *implementation* need not be the same thing. – Eric Lippert Jul 18 '13 at 14:59
  • An instance of a type which implements `IEnumerable` is *assignable* to a variable of type `IEnumerable`, even if it does not *implement* that type. So which do you care about, assignability, or implementation? – Eric Lippert Jul 18 '13 at 15:00
  • I've added an example to the original post for context. Am I approaching this wrong? – Haighstrom Jul 18 '13 at 15:02
  • @Haighstrom: Your approach raises a flag in my mind: any time you make a decision based on the specific details of the argument given to a generic type parameter, you're writing code that is not really in the spirit of generics. But I am actually more concerned that you understand the difference between a type object and an instance of that type. The questions "are all animals of a given type -- say, tigers -- also mammals?" and "is this specific animal -- a tiger -- a mammal?" have the same answer: yes. The question "is the abstract notion of 'tiger' a mammal?" is not the same question. – Eric Lippert Jul 18 '13 at 16:08
  • Think of the idea you get in your head when you think of the class of all tigers: that idea does not give birth to live young, have hair, or make its own milk. That *idea* is not a mammal. The *description* of a tiger is not a mammal; a *tiger* is a mammal. That's what you're asking when you say `typeof(T) is IFoo` -- the answer is almost certainly going to be "false", because *a description of all Ts does not necessarily have any property in common with an actual T*. – Eric Lippert Jul 18 '13 at 16:11
3

Some differences:

A: With IsAssignableFrom you don't need any object instances, (only System.Type objects), which is very useful during reflection.

B: With the is keyword get some compile-time hints if the types are always/never compatible (at least with resharper)

C: They are kind of the opposites. IsAssignableFrom checks if an object of the type passed as argument can be assigned to a variable of the other type. The is keyword checks if the object on the left side of the keyword can be assigned to a variable of the type to the right of the keyword.

lightbricko
  • 2,649
  • 15
  • 21
2

typeof(Class) is IInterface will always evaluate to false, because the type of typeof(Class) is RuntimeType. The right way to use is on an instance of the given class, e.g.

Class c = // something
bool isIt = c is IInterface;

is should be used when you want to know whether a value is convertible to a type that is known at compile time.

IsAssignableFrom should be used when one or both of the types are only known at runtime. E.g. someType.IsAssignableFrom(someOtherType). If both types are known at compile time, e.g. typeof(IInterface).IsAssignableFrom(typeof(Class));, you can know the answer by looking up the definition of Class, and it doesn't really make sense to check it at runtime.

Tim S.
  • 55,448
  • 7
  • 96
  • 122