Type Checking: typeof, GetType, or is?

前端 未结 14 2266
北海茫月
北海茫月 2020-11-22 00:49

I\'ve seen many people use the following code:

Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

But I know you could also

相关标签:
14条回答
  • 2020-11-22 01:23

    I prefer is

    That said, if you're using is, you're likely not using inheritance properly.

    Assume that Person : Entity, and that Animal : Entity. Feed is a virtual method in Entity (to make Neil happy)

    class Person
    {
      // A Person should be able to Feed
      // another Entity, but they way he feeds
      // each is different
      public override void Feed( Entity e )
      {
        if( e is Person )
        {
          // feed me
        }
        else if( e is Animal )
        {
          // ruff
        }
      }
    }
    

    Rather

    class Person
    {
      public override void Feed( Person p )
      {
        // feed the person
      }
      public override void Feed( Animal a )
      {
        // feed the animal
      }
    }
    
    0 讨论(0)
  • 2020-11-22 01:24

    It depends on what I'm doing. If I need a bool value (say, to determine if I'll cast to an int), I'll use is. If I actually need the type for some reason (say, to pass to some other method) I'll use GetType().

    0 讨论(0)
  • 2020-11-22 01:26

    The last one is cleaner, more obvious, and also checks for subtypes. The others do not check for polymorphism.

    0 讨论(0)
  • 2020-11-22 01:27

    If you're using C# 7, then it is time for an update to Andrew Hare's great answer. Pattern matching has introduced a nice shortcut that gives us a typed variable within the context of the if statement, without requiring a separate declaration/cast and check:

    if (obj1 is int integerValue)
    {
        integerValue++;
    }
    

    This looks pretty underwhelming for a single cast like this, but really shines when you have many possible types coming into your routine. The below is the old way to avoid casting twice:

    Button button = obj1 as Button;
    if (button != null)
    {
        // do stuff...
        return;
    }
    TextBox text = obj1 as TextBox;
    if (text != null)
    {
        // do stuff...
        return;
    }
    Label label = obj1 as Label;
    if (label != null)
    {
        // do stuff...
        return;
    }
    // ... and so on
    

    Working around shrinking this code as much as possible, as well as avoiding duplicate casts of the same object has always bothered me. The above is nicely compressed with pattern matching to the following:

    switch (obj1)
    {
        case Button button:
            // do stuff...
            break;
        case TextBox text:
            // do stuff...
            break;
        case Label label:
            // do stuff...
            break;
        // and so on...
    }
    

    EDIT: Updated the longer new method to use a switch as per Palec's comment.

    0 讨论(0)
  • 2020-11-22 01:27

    I had a Type-property to compare to and could not use is (like my_type is _BaseTypetoLookFor), but I could use these:

    base_type.IsInstanceOfType(derived_object);
    base_type.IsAssignableFrom(derived_type);
    derived_type.IsSubClassOf(base_type);
    

    Notice that IsInstanceOfType and IsAssignableFrom return true when comparing the same types, where IsSubClassOf will return false. And IsSubclassOf does not work on interfaces, where the other two do. (See also this question and answer.)

    public class Animal {}
    public interface ITrainable {}
    public class Dog : Animal, ITrainable{}
    
    Animal dog = new Dog();
    
    typeof(Animal).IsInstanceOfType(dog);     // true
    typeof(Dog).IsInstanceOfType(dog);        // true
    typeof(ITrainable).IsInstanceOfType(dog); // true
    
    typeof(Animal).IsAssignableFrom(dog.GetType());      // true
    typeof(Dog).IsAssignableFrom(dog.GetType());         // true
    typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true
    
    dog.GetType().IsSubclassOf(typeof(Animal));            // true
    dog.GetType().IsSubclassOf(typeof(Dog));               // false
    dog.GetType().IsSubclassOf(typeof(ITrainable)); // false
    
    0 讨论(0)
  • 2020-11-22 01:30

    Use typeof when you want to get the type at compilation time. Use GetType when you want to get the type at execution time. There are rarely any cases to use is as it does a cast and, in most cases, you end up casting the variable anyway.

    There is a fourth option that you haven't considered (especially if you are going to cast an object to the type you find as well); that is to use as.

    Foo foo = obj as Foo;
    
    if (foo != null)
        // your code here
    

    This only uses one cast whereas this approach:

    if (obj is Foo)
        Foo foo = (Foo)obj;
    

    requires two.

    Update (Jan 2020):

    • As of C# 7+, you can now cast inline, so the 'is' approach can now be done in one cast as well.

    Example:

    if(obj is Foo newLocalFoo)
    {
        // For example, you can now reference 'newLocalFoo' in this local scope
        Console.WriteLine(newLocalFoo);
    }
    
    0 讨论(0)
提交回复
热议问题