Difference between the use of typeof and is

40

In C # when I need to check if a variable is of a certain type, I usually use the is :

if(qualquerVariavel is int)
    Console.Write("A variável é int");

I know you can also check the type of a variable in other ways, one of them is using typeof :

if(qualquerVariavel.GetType() == typeof(int))
    Console.WriteLine("A variável é int");

What is the difference between these two operators? There are others who "do the same thing", but with a small difference?

    
asked by LINQ 11.09.2015 в 21:14

3 answers

41
  • is checks the entire inheritance structure of the object;
  • typeof() returns the exact type of the object.

To illustrate better:

class Animal { } 
class Cachorro : Animal { }

var a = new Cachorro();

Console.WriteLine(a.GetType() == typeof(Animal)) // false 
Console.WriteLine(a is Animal)                   // true 
Console.WriteLine(a.GetType() == typeof(Cachorro))    // true
    
11.09.2015 / 21:17
15

An important detail is that if the variable is null , the is operator always returns false.

string s = null;

s is string == false
s is object == false
s is int    == false

Needless to say, GetType does not work with null.

At first glance, this may appear to be inconsistent behavior. But Eric Lippert (former member of the C # design committee) explains why here: What the meaning of is is

  

The fact that a null reference may be assigned to a variable string does not make the null reference the string, any more than the fact that your driveway is empty means that an empty driveway contains the Honda Civic. The answers to the question "Is this reference to a legitimate reference to an object of the given type?", And is it not a legitimate question reference.

Or

  

The fact that a null reference can be assigned to a string variable does not make the null reference a string; such as the fact that a garage can be empty, does not mean that an empty garage contains a Honda Civic. The is operator does not answer the question: "Can I assign this reference to a variable of this type?". It answers the question "Is this reference a legitimate reference to an object of this type?", And null is not a legitimate reference.

Consequently, we can also observe that a non-null reference of type Nullable<T> is also a valid reference of type T , and vice versa. Exemplifying:

int i = 1;

i is int  == true
i is int? == true

int? ni = 1;

ni is int  == true
ni is int? == true
    
11.09.2015 в 21:30
9

Existing answers already speak the difference. But C # 7 gave a new function to is .

When do you need to check the type of the object? When you do not know the exact type you are getting.

What do you do to use this object with the type you checked? It probably makes a cast for the type and then has access to the available members of that type. If you do not need to access these members you do not have to cast , and then you do not have to check what type it is.

As in most cases cast is what you want, C # 7 allows this to be done automatically.

using static System.Console;
using System;

public class Program {
    public static void Main() {
        Teste(DateTime.Now);
        WriteLine();
        Teste("ok");
    }

    public static void Teste(object qualquerVariavel) {
        if(qualquerVariavel is DateTime x) {
            WriteLine($"A variável é DateTime e seu valor é {x.DayOfWeek}");
        }
        if(qualquerVariavel is DateTime) {
            WriteLine($"A variável é DateTime e seu valor é {((DateTime)qualquerVariavel).DayOfWeek}");
        }
        if(qualquerVariavel is DateTime) {
//          WriteLine($"A variável é DateTime e seu valor é {qualquerVariavel.DayOfWeek}"); //isto não compila
        }
        if(qualquerVariavel is "ok") {
            WriteLine($"A variável é string e vale ok");
        }
        switch (qualquerVariavel) {
            case null:
                WriteLine("nulo");
                break;
            case int i:
                WriteLine(i);
                break;
            case string s:
                WriteLine(s);
                break;
            case DateTime d:
                WriteLine(d.DayOfWeek);
                break;
        }
    }
}

See working on .NET Fiddle . Also put it on GitHub for future reference .

Note that the variable is declared inside if or case but has method scope, so it can not use the same name in each. This is because it is not within the if block, the condition itself does not create a new scope.

Using switch may not appear to be using is , but just as == is implied in it, is is also there even if you do not see it.

    
24.04.2017 в 18:02