c# 使用模式匹配以及 is 和 as 运算符安全地进行强制转换

作者:olprod 时间:2022-11-23 09:47:51 

由于是多态对象,基类类型的变量可以保存派生类型。 要访问派生类型的实例成员,必须将值强制转换 * 生类型。 但是,强制转换会引发 InvalidCastException 风险。 C# 提供模式匹配语句,该语句只有在成功时才会有条件地执行强制转换。 C# 还提供 is 和 as 运算符来测试值是否属于特定类型。

下面的示例演示如何使用模式匹配 is 语句:


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 { }

class Program
{
 static void Main(string[] args)
 {
   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");
   }
 }
}

前面的示例演示了模式匹配语法的一些功能。 if (a is Mammal m) 语句将测试与初始化赋值相结合。 只有在测试成功时才会进行赋值。 变量 m 仅在已赋值的嵌入式 if 语句的范围内。 以后无法在同一方法中访问 m。 前面的示例还演示了如何使用 as 运算符将对象转换为指定类型。
也可以使用同一语法来测试可为 null 的值类型是否具有值,如以下示例所示:


class Program
{
 static void Main(string[] args)
 {
   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(System.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(System.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。 模式匹配 is 语句不允许可以为 null 值的类型,如 int? 或 Nullable<int>,但你可以测试任何其他值类型。 上述示例中的 is 模式不局限于可为空的值类型。 也可以使用这些模式测试引用类型的变量具有值还是为 null。
前面的示例还演示如何在变量为其他类型的 switch 语句中使用类型模式。
如果需要测试变量是否为给定类型,但不将其分配给新变量,则可以对引用类型和可以为 null 的值类型使用 is 和 as 运算符。 以下代码演示如何在引入模式匹配以测试变量是否为给定类型前,使用 C# 语言中的 is 和 as 语句:


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 { }

class Program
{
 static void Main(string[] args)
 {
   // Use the is operator to verify the type.
   // before performing a cast.
   Giraffe g = new Giraffe();
   UseIsOperator(g);

// Use the as operator and test for null
   // before referencing the variable.
   UseAsOperator(g);

// Use the as operator to test
   // an incompatible type.
   SuperNova sn = new SuperNova();
   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 != 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 != null)
   {
     Console.WriteLine(j);
   }
   else
   {
     Console.WriteLine("Could not convert " + val.ToString());
   }
 }
}

正如你所看到的,将此代码与模式匹配代码进行比较,模式匹配语法通过在单个语句中结合测试和赋值来提供更强大的功能。 尽量使用模式匹配语法。

来源:https://github.com/dotnet/docs.zh-cn/blob/live/docs/csharp/how-to/safely-cast-using-pattern-matching-is-and-as-operators.md

标签:c#,模式匹配,强制转换,is,as,运算符
0
投稿

猜你喜欢

  • 使用IntelliJ IDEA搭建SSM框架的图文教程

    2022-06-14 00:56:19
  • Spring Boot支持Crontab任务改造的方法

    2023-08-08 20:20:24
  • C#图像处理之图像平移的方法

    2021-12-16 08:38:37
  • java(包括springboot)读取resources下文件方式实现

    2021-06-03 20:16:06
  • 关于AndroidStudio R文件莫名其妙缺失的快速解决方法

    2023-02-24 21:59:06
  • C#字符串的常用操作工具类代码分享

    2022-08-30 16:52:24
  • 详谈java 堆区、方法区和栈区

    2023-11-23 18:35:22
  • Android自定义短信验证码组件

    2022-10-06 00:30:13
  • Java动态脚本Groovy

    2023-12-05 03:25:50
  • java编程约瑟夫问题实例分析

    2022-04-05 22:32:08
  • Android11文件管理权限申请详细介绍

    2023-08-28 17:41:47
  • 实现Android 滑动退出Activity的功能

    2023-04-24 03:00:34
  • selenium+java破解极验滑动验证码的示例代码

    2022-11-19 21:52:01
  • Java实现淘宝秒杀聚划算抢购自动提醒源码

    2022-09-11 10:11:53
  • 详解tryAcquire()、addWaiter()、acquireQueued()

    2022-07-30 10:24:05
  • Java的Struts框架中登陆功能的实现和表单处理器的使用

    2022-05-20 23:44:45
  • Java数据结构学习之树

    2022-01-19 23:40:58
  • 解决Java中OutOfMemoryError的问题

    2023-01-26 13:51:03
  • c#实现用SQL池,多线程定时批量执行SQL语句的方法

    2023-12-25 01:03:55
  • Android中使用Spinner实现下拉列表功能

    2022-03-03 20:50:35
  • asp之家 软件编程 m.aspxhome.com