Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Dado que los objetos son polimórficos, es posible que una variable de un tipo de clase base contenga un tipo derivado. Para acceder a los miembros de instancia del tipo derivado, es necesario volver a convertir el valor en el tipo derivado. Pero una conversión conlleva el riesgo de producir una InvalidCastException. C# proporciona instrucciones de coincidencia de patrones que realizan una conversión condicionalmente, solo si se va a realizar correctamente. C# también proporciona los operadores is y como para probar si un valor es de un tipo determinado.
En el ejemplo siguiente se muestra cómo usar la instrucción is
de coincidencia de patrones.
var g = new Giraffe();
var a = new Animal();
FeedMammals(g);
FeedMammals(a);
// Output:
// Eating.
// Animal is not a Mammal
SuperNova sn = new SuperNova();
TestForMammals(g);
TestForMammals(sn);
// Output:
// I am an animal.
// SuperNova is not a Mammal
static void FeedMammals(Animal a)
{
if (a is Mammal m)
{
m.Eat();
}
else
{
// variable 'm' is not in scope here, and can't be used.
Console.WriteLine($"{a.GetType().Name} is not a Mammal");
}
}
static void TestForMammals(object o)
{
// You also can use the as operator and test for null
// before referencing the variable.
var m = o as Mammal;
if (m != null)
{
Console.WriteLine(m.ToString());
}
else
{
Console.WriteLine($"{o.GetType().Name} is not a Mammal");
}
}
class Animal
{
public void Eat() { Console.WriteLine("Eating."); }
public override string ToString()
{
return "I am an animal.";
}
}
class Mammal : Animal { }
class Giraffe : Mammal { }
class SuperNova { }
En el ejemplo anterior se muestran algunas características de la sintaxis de coincidencia de patrones. La if (a is Mammal m)
instrucción combina la prueba con una asignación de inicialización. La asignación solo se produce cuando la prueba se realiza correctamente. La variable m
solo tiene alcance dentro de la instrucción incrustada if
donde se ha asignado. No se puede acceder a m
más adelante en el mismo método. En el ejemplo anterior también se muestra cómo usar el as
operador para convertir un objeto en un tipo especificado.
También puede usar la misma sintaxis para probar si un tipo de valor que acepta valores NULL tiene un valor, como se muestra en el ejemplo siguiente:
int i = 5;
PatternMatchingNullable(i);
int? j = null;
PatternMatchingNullable(j);
double d = 9.78654;
PatternMatchingNullable(d);
PatternMatchingSwitch(i);
PatternMatchingSwitch(j);
PatternMatchingSwitch(d);
static void PatternMatchingNullable(ValueType? val)
{
if (val is int j) // Nullable types are not allowed in patterns
{
Console.WriteLine(j);
}
else if (val is null) // If val is a nullable type with no value, this expression is true
{
Console.WriteLine("val is a nullable type with the null value");
}
else
{
Console.WriteLine("Could not convert " + val.ToString());
}
}
static void PatternMatchingSwitch(ValueType? val)
{
switch (val)
{
case int number:
Console.WriteLine(number);
break;
case long number:
Console.WriteLine(number);
break;
case decimal number:
Console.WriteLine(number);
break;
case float number:
Console.WriteLine(number);
break;
case double number:
Console.WriteLine(number);
break;
case null:
Console.WriteLine("val is a nullable type with the null value");
break;
default:
Console.WriteLine("Could not convert " + val.ToString());
break;
}
}
En el ejemplo anterior se muestran otras características de coincidencia de patrones para usarlas con conversiones. Puede probar una variable para el patrón NULL comprobando específicamente el null
valor. Cuando el valor en tiempo de ejecución de la variable es null
, una is
instrucción que comprueba un tipo siempre devuelve false
. La instrucción de coincidencia is
de patrones no permite un tipo de valor anulable, como int?
o Nullable<int>
, pero se puede probar cualquier otro tipo de valor. Los is
patrones del ejemplo anterior no se limitan a los tipos de valor que aceptan valores NULL. También puede usar esos patrones para probar si una variable de un tipo de referencia tiene un valor o es null
.
En el ejemplo anterior también se muestra cómo se usa el patrón de tipo en una switch
instrucción donde la variable puede ser uno de muchos tipos diferentes.
Si desea probar si una variable es un tipo determinado, pero no la asigna a una nueva variable, puede usar los is
operadores y as
para los tipos de referencia y los tipos de valor que aceptan valores NULL. En el código siguiente se muestra cómo usar las is
instrucciones y as
que formaban parte del lenguaje C# antes de que se introdujera la coincidencia de patrones para probar si una variable es de un tipo determinado:
// Use the is operator to verify the type.
// before performing a cast.
Giraffe g = new();
UseIsOperator(g);
// Use the as operator and test for null
// before referencing the variable.
UseAsOperator(g);
// Use pattern matching to test for null
// before referencing the variable
UsePatternMatchingIs(g);
// Use the as operator to test
// an incompatible type.
SuperNova sn = new();
UseAsOperator(sn);
// Use the as operator with a value type.
// Note the implicit conversion to int? in
// the method body.
int i = 5;
UseAsWithNullable(i);
double d = 9.78654;
UseAsWithNullable(d);
static void UseIsOperator(Animal a)
{
if (a is Mammal)
{
Mammal m = (Mammal)a;
m.Eat();
}
}
static void UsePatternMatchingIs(Animal a)
{
if (a is Mammal m)
{
m.Eat();
}
}
static void UseAsOperator(object o)
{
Mammal? m = o as Mammal;
if (m is not null)
{
Console.WriteLine(m.ToString());
}
else
{
Console.WriteLine($"{o.GetType().Name} is not a Mammal");
}
}
static void UseAsWithNullable(System.ValueType val)
{
int? j = val as int?;
if (j is not null)
{
Console.WriteLine(j);
}
else
{
Console.WriteLine("Could not convert " + val.ToString());
}
}
class Animal
{
public void Eat() => Console.WriteLine("Eating.");
public override string ToString() => "I am an animal.";
}
class Mammal : Animal { }
class Giraffe : Mammal { }
class SuperNova { }
Como puede ver comparando este código con el código de coincidencia de patrones, la sintaxis de coincidencia de patrones proporciona características más sólidas combinando la prueba y la asignación en una sola instrucción. Use la sintaxis de coincidencia de patrones siempre que sea posible.