Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Так как объекты являются полиморфными, переменная базового класса может содержать производный тип. Чтобы получить доступ к членам экземпляра производного типа, необходимо привести значение в производный тип. Однако гипс создает риск бросания InvalidCastException. C# предоставляет операторы шаблонного сопоставления, которые выполняют преобразование условно только в том случае, если оно завершится успешно. C# также предоставляет операторы is и as, которые позволяют проверить, является ли значение определенного типа.
В следующем примере показано, как использовать оператор сопоставления is
шаблонов:
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 { }
В предыдущем примере показаны некоторые функции синтаксиса сопоставления шаблонов. Инструкция if (a is Mammal m)
объединяет тест с назначением инициализации. Назначение происходит только при успешном выполнении теста. Переменная m
находится только в области видимости внедренной if
инструкции, где ей было присвоено значение. Вы не можете получить доступ m
позже в том же методе. В предыдущем примере также показано, как использовать as
оператор для преобразования объекта в указанный тип.
Вы также можете использовать тот же синтаксис для тестирования, если тип значения, допускающий значение NULL , имеет значение, как показано в следующем примере:
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;
}
}
В предыдущем примере показаны другие функции сопоставления шаблонов для использования с преобразованиями. Вы можете протестировать переменную для шаблона NULL, проверив конкретно значение null
. Когда значение переменной в среде выполнения равно null
, инструкция is
, проверяющая тип, всегда возвращает false
. Оператор сопоставления шаблонов не разрешает тип значения с возможным значением NULL, например is
или int?
, но можно тестировать любой другой тип значения.
is
Шаблоны из предыдущего примера не ограничиваются типами значений, допускающих значение NULL. Эти шаблоны также можно использовать для проверки того, имеет ли переменная ссылочного типа значение или она null
.
В предыдущем примере также показано, как использовать шаблон типа в операторе switch
, где переменная может быть одного из нескольких различных типов.
Если вы хотите проверить, является ли переменная заданным типом, но не назначьте ее новой переменной, можно использовать is
as
операторы для ссылочных типов и типов значений, допускающих значение NULL. В следующем коде показано, как использовать is
и as
инструкции, которые были частью языка C# перед введением сопоставления с шаблонами, чтобы проверить, является ли переменная заданного типа.
// 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 { }
Как видно, сравнивая этот код с кодом сопоставления шаблонов, синтаксис сопоставления шаблонов обеспечивает более надежные функции, сочетая тест и назначение в одной инструкции. По возможности используйте синтаксис сопоставления шаблонов.