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

 更新时间:2020年12月8日 11:35  点击:2279

由于是多态对象,基类类型的变量可以保存派生类型。 要访问派生类型的实例成员,必须将值强制转换回派生类型。 但是,强制转换会引发 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());
    }
  }
}

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

以上就是c# 使用模式匹配以及 is 和 as 运算符安全地进行强制转换的详细内容,更多关于c# 强制转换的资料请关注猪先飞其它相关文章!

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • Mybatis Plus select 实现只查询部分字段

    这篇文章主要介绍了Mybatis Plus select 实现只查询部分字段的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-01
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • 解决Mybatis 大数据量的批量insert问题

    这篇文章主要介绍了解决Mybatis 大数据量的批量insert问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-09
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25