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 operador is
comprueba si el tipo en tiempo de ejecución de una expresión es compatible con un tipo determinado. El operador as
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 operador typeof
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 tipo en tiempo de ejecución del resultado de una expresión es
T
.El tipo en tiempo de ejecución del resultado de una expresión deriva del tipo
T
, implementa una interfazT
, o bien otra conversión de referencia implícita existe enT
.El tipo en tiempo de ejecución del resultado de una expresión es un tipo de valor que admite un valor NULL con el tipo subyacente
T
y Nullable<T>.HasValue estrue
.Existe una conversión boxing o unboxing del tipo en tiempo de ejecución del resultado de una expresión al tipo
T
.
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#: