C#使用is、as关键字以及显式强转实现引用类型转换
作者:Darren?Ji 发布时间:2023-01-29 16:15:27
在C#中,当引用类型需要转换的时候,经常会用到关键字is、as以及显式强转。本篇来体验这三者的用法。
先来梳理.NET引用类型转换的"约定俗成",或者叫"惯例":
子类可以隐式转换为父类/基类,也就是"里氏替换原则"所说的:子类必须能够替换其父类/基类。
父类/基类转换为子类时,必须进行显式类型强转。
子类转换成父类
class Program
{
static void Main(string[] args)
{
Animal animal = new Dog(){Name = "Dog",Age = 1};
Console.WriteLine(animal.Name);
Console.ReadKey();
}
}
public class Animal
{
public string Name { get; set; }
}
public class Dog : Animal
{
public int Age { get; set; }
}
输出结果:Dog
以上,体验了子类转换成父类,从中可以看出:子类Dog确实能替换父类Animal,换句话说,子类就是父类,子类的实例可以赋值给父类的变量,不需要as,不需要强转,一切都是隐式发生,很好地体现了"里氏替换原则"。
父类转换为子类,父类变量通过子类赋值而创建
父类as成子类:
Animal animal = new Dog(){Name = "Dog",Age = 1};
Dog dog = animal as Dog;
Console.WriteLine(dog.Name + " " + dog.Age);
Console.ReadKey();
输出结果:Dog 1
父类显式强转成子类
Animal animal = new Dog(){Name = "Dog",Age = 1};
Dog dog = (Dog)animal;
Console.WriteLine(dog.Name + " " + dog.Age);
Console.ReadKey();
输出结果:Dog 1
以上,不管是使用as还是显式强转,父类都可以转换成子类,但是有前提的:把子类实例赋值给父类变量。
父类转换为子类,父类变量通过自身构造函数而创建
父类as成子类失败:
Animal animal = new Animal(){Name = "Sheep"};
Dog dog = animal as Dog;
Console.WriteLine(dog.Name + " " + dog.Age);
Console.ReadKey();
输出结果:报"NullReferenceException"错
可见,当父类变量通过自身构造函数而创建时,无法将父类转换成子类。
(1)为了避免as的时候报"NullReferenceException"错,引入关键is做类型判断:
Animal animal = new Animal(){Name = "Sheep"};
if (animal is Dog)
{
Dog dog = animal as Dog;
Console.WriteLine(dog.Name + " " + dog.Age);
}
else
{
Console.WriteLine("animal不能转换为Dog");
}
Console.ReadKey();
输出结果:animal不能转换为Dog
(2)用as做类型转换的时候,如果转换失败,返回null。根据这点,也可以通过判断as转换后的返回值是否为null,来避免报错:
Animal animal = new Animal(){Name = "Sheep"};
Dog dog = animal as Dog;
if (dog != null)
{
Console.WriteLine(dog.Name + " " + dog.Age);
}
else
{
Console.WriteLine("animal不能转换为Dog");
}
Console.ReadKey();
输出结果:animal不能转换为Dog
父类显式强转成子类失败
Animal animal = new Animal(){Name = "Sheep"};
Dog dog = (Dog) animal;
Console.WriteLine(dog.Name + " " + dog.Age);
Console.ReadKey();
输出结果:报"InvalidCastException"错
可见,当父类变量通过自身构造函数而创建时,无法将父类转换成子类。
为了避免显示强转时报"InvalidCastException"错,引入关键字is做类型判断:
Animal animal = new Animal(){Name = "Sheep"};
if (animal is Dog)
{
Dog dog = (Dog)animal;
Console.WriteLine(dog.Name + " " + dog.Age);
}
else
{
Console.WriteLine("animal不能转换为Dog");
}
Console.ReadKey();
输出结果:animal不能转换为Dog
来源:https://www.cnblogs.com/darrenji/p/3831421.html
猜你喜欢
- 没人会喜欢空指针异常!有什么方法可以避免它们吗?或许吧。。本文将讨论到以下几种技术1.Optional类型(Java 8中新引入的)2.Ob
- 本文实例为大家分享了Java swing读取txt文件实现学生考试系统的具体代码,供大家参考,具体内容如下主要实现了一个简单的倒计时答题系统
- 1、普通用户与系统管理员用户的权限要有严格的区分。如果一个普通用户在使用查询语句中嵌入另一个Drop Table语句,那么是否允许
- 前言:2022年Java将有什么新的特性和改进,我相信很多Java开发者都想知道。结合Java语言架构师布莱恩·格茨(
- 1、#{}是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的set
- Springboot swagger-ui.html访问不到问题在前面的Swagger2的基本配置中是可以访问到swagger-ui.htm
- CyclicBarrier是什么CyclicBarrier是Java并发包中提供的一种同步工具类,它可以让多个线程在某个屏障处等待,直到所有
- 介绍 在开发过程中,我们有时候会遇到非接口调用而出发程序执行任务的一些场景,比如我们使用quartz定时框架通过配置文件来启动定时任务时,
- 前言用过Spring的人多多少少也都用过@Async注解,至于作用嘛,看注解名,大概能猜出来,就是在方法执行的时候进行异步执行。一、如何使用
- 摘要:介绍使用Java Stream流排序器Comparator对List集合进行多字段排序的方法,包括复杂实体对象多字段升降序排序方法。综
- Maven 多profile及指定编译要点项目A依赖项目B,项目A、B都有对应的多个profile,通过mvn –P参数指定profile,
- C#调用c++dll文件是一件很麻烦的事情,首先面临的是数据类型转换的问题,相信经常做c#开发的都和我一样把学校的那点c++底子都忘光了吧(
- 前文本章是关于Java流程控制语句的最全汇总,本篇为汇总中篇。流程是人们生活中不可或缺的一部分,它表示人们每天都在按照一定的流程做事。比如出
- LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,LRU缓存就是使用这种原理实现,简单的说就是缓存一定量
- 这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚。后来终于找到了原因。如果你也出现了这种情况,可以从下
- 这篇文章主要介绍了Spring ApplicationListener * 用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具
- 介绍Java中的享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享尽可能多的对象来减少内存占用和提高性能.Ja
- 一、BigInteger介绍如果在操作的时候一个整型数据已经超过了整数的最大类型长度 long 的话,则此数据就无法装入,所以,此时要使用
- 本文实例讲述了Java使用JDBC实现Oracle用户认证的方法。分享给大家供大家参考,具体如下:两天时间写的小品,以前的J2EE环境基本使
- 概述归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有