Operadores de prueba de tipos y expresión de conversión: is, as, typeof y conversiones

Estos operadores y expresiones realizan la comprobación de tipos o la conversión de tipos. El isoperador comprueba si el tipo en tiempo de ejecución de una expresión es compatible con un tipo determinado. El asoperador convierte explícitamente una expresión a un tipo determinado si su tipo en tiempo de ejecución es compatible con ese tipo. Las expresiones de conversión realizan una conversión explícita a un tipo de destino. El typeofoperador obtiene la instancia System.Type para un tipo.

Operador is

El operador is comprueba si el tipo en tiempo de ejecución del resultado de una expresión es compatible con un tipo determinado. El operador is también prueba el resultado de una expresión en relación con un patrón.

La expresión con el operador is de prueba de tipos tiene el formato siguiente:

E is T

donde E es una expresión que devuelve un valor y T es el nombre de un tipo o un parámetro de tipo. E no puede ser un método anónimo ni una expresión lambda.

El operador is devuelve true cuando el resultado de una expresión es distinto de NULL y se cumple cualquiera de las condiciones siguientes:

El operador is no toma en consideración las conversiones definidas por el usuario.

En el ejemplo siguiente se muestra que el operador is devuelve true si el tipo en tiempo de ejecución del resultado de una expresión se deriva de un tipo determinado, es decir, existe una conversión de referencia entre tipos:

public class Base { }

public class Derived : Base { }

public static class IsOperatorExample
{
    public static void Main()
    {
        object b = new Base();
        Console.WriteLine(b is Base);  // output: True
        Console.WriteLine(b is Derived);  // output: False

        object d = new Derived();
        Console.WriteLine(d is Base);  // output: True
        Console.WriteLine(d is Derived); // output: True
    }
}

En el ejemplo siguiente se muestra que el operador is tiene en cuenta las conversiones boxing y unboxing pero no considera las conversiones numéricas:

int i = 27;
Console.WriteLine(i is System.IFormattable);  // output: True

object iBoxed = i;
Console.WriteLine(iBoxed is int);  // output: True
Console.WriteLine(iBoxed is long);  // output: False

Para obtener información acerca de las conversiones de C#, vea el capítulo Conversiones de la especificación del lenguaje C#.

Prueba de tipos con coincidencia de patrones

El operador is también prueba el resultado de una expresión en relación con un patrón. En el ejemplo siguiente se muestra cómo usar un patrón de declaración para comprobar el tipo en tiempo de ejecución de una expresión:

int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
    Console.WriteLine(a + b);  // output 30
}

Para obtener información sobre los patrones admitidos, consulte Patrones.

Operador as

El operador as convierte explícitamente el resultado de una expresión en una referencia determinada o un tipo de valor que acepta valores NULL. Si la conversión no es posible, el operador as devuelve null. A diferencia de la expresión Cast, el operador as no genera nunca una excepción.

La expresión con el formato

E as T

donde E es una expresión que devuelve un valor y T es el nombre de un tipo o un parámetro de tipo produce el mismo resultado que

E is T ? (T)(E) : (T)null

salvo que E solo se evalúa una vez.

El operador as solo considera las conversiones de referencia, las que aceptan valores NULL, boxing y unboxing. No puede usar el operador as para realizar una conversión definida por el usuario. Para ello, use una expresión Cast.

En el siguiente ejemplo se muestra el uso del operador as:

IEnumerable<int> numbers = new List<int>(){10, 20, 30};
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
    Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]);  // output: 40
}

Nota:

Como se muestra en el ejemplo anterior, se necesita comparar el resultado de la expresión as con null para comprobar si una conversión es correcta. Puede usar el operador is para probar si la conversión es correcta y, si es así, asignar su resultado a una nueva variable.

Expresión Cast

Una expresión de conversión con el formato (T)E realiza una conversión explícita del resultado de la expresión E al tipo T. Si no existe ninguna conversión explícita del tipo de E al tipo T, se producirá un error en tiempo de compilación. En el tiempo de ejecución, una conversión explícita podría no completarse correctamente y una expresión de conversión podría generar una excepción.

El ejemplo siguiente muestra las conversiones explícitas numérica y de referencia:

double x = 1234.7;
int a = (int)x;
Console.WriteLine(a);   // output: 1234

int[] ints = [10, 20, 30];
IEnumerable<int> numbers = ints;
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count);  // output: 3
Console.WriteLine(list[1]);  // output: 20

Para obtener más información sobre las conversiones explícitas, vea la sección Conversiones explícitas de la especificación del lenguaje C#. Para obtener información sobre cómo definir una conversión personalizada de tipo explícito o implícito, vea Operadores de conversión definidos por el usuario.

Otros usos de ()

También puede utilizar paréntesis para llamar a un método o invocar un delegado.

Sirven además para ajustar el orden en el que se van a evaluar operaciones en una expresión. Para obtener más información, vea Operadores de C# (referencia de C#).

typeof (operador)

El operador typeof obtiene la instancia System.Type para un tipo. El argumento del operador typeof debe ser el nombre de un tipo o un parámetro de tipo, como se muestra en el ejemplo siguiente:

void PrintType<T>() => Console.WriteLine(typeof(T));

Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
// Output:
// System.Collections.Generic.List`1[System.String]
// System.Int32
// System.Int32
// System.Collections.Generic.Dictionary`2[System.Int32,System.Char]

El argumento no debe ser un tipo que requiera anotaciones de metadatos. Algunos tipos de ejemplo son:

  • dynamic
  • string? (o cualquier tipo de referencia que acepte valores NULL)

Estos tipos no se representan directamente en los metadatos. Los tipos incluyen atributos que describen el tipo subyacente. En ambos casos se puede usar el tipo subyacente. En lugar de dynamic, se puede usar object. En lugar de string?, se puede usar string.

También se puede usar el operador typeof con tipos genéricos sin enlazar. El nombre de un tipo genérico sin enlazar debe contener el número apropiado de comas, que es inferior en una unidad al número de parámetros de tipo. En el siguiente ejemplo se muestra el uso del operador typeof con un tipo genérico sin enlazar:

Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]

Una expresión no puede ser un argumento del operador typeof. Para obtener la instancia de System.Type para el tipo en tiempo de ejecución del resultado de una expresión, use el método Object.GetType.

Prueba de tipos con el operador typeof

Use el operador typeof para comprobar si el tipo en tiempo de ejecución del resultado de la expresión coincide exactamente con un tipo determinado. En el ejemplo siguiente se muestra la diferencia entre la comprobación de tipos realizada con el operador typeof y el operador is:

public class Animal { }

public class Giraffe : Animal { }

public static class TypeOfExample
{
    public static void Main()
    {
        object b = new Giraffe();
        Console.WriteLine(b is Animal);  // output: True
        Console.WriteLine(b.GetType() == typeof(Animal));  // output: False

        Console.WriteLine(b is Giraffe);  // output: True
        Console.WriteLine(b.GetType() == typeof(Giraffe));  // output: True
    }
}

Posibilidad de sobrecarga del operador

Los operadores is, as y typeof no se pueden sobrecargar.

Un tipo definido por el usuario no se puede sobrecargar el operador (), pero puede definir conversiones de tipos personalizadas que pueden realizarse mediante una expresión de conversión. Para obtener más información, vea Operadores de conversión definidos por el usuario.

Especificación del lenguaje C#

Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:

Consulte también