前言

当年写的比较差:https://www.cnblogs.com/aoximin/p/12965408.html,所以特来重新写一遍。

正文

首先为什么会出现is 和 as 呢?

因为是为了有需要检验的地方,如果直接使用显示转换的话,那么可能直接报错了。

namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
object obj = new Student();
var c = (Teacher)obj;
} public class Student
{ } public class Teacher
{
}
}
}

比如这样肯定会报错的, 因为在运行的时候我们来查看一下il语句。

.method private hidebysig static
void Main (
string[] args
) cil managed
{
.custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
01 00 01 00 00
)
// Method begins at RVA 0x20a4
// Header size: 12
// Code size: 15 (0xf)
.maxstack 1
.entrypoint
.locals init (
[0] object obj,
[1] class ConsoleApp4.Program/Teacher c
) IL_0000: nop
IL_0001: newobj instance void ConsoleApp4.Program/Student::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: castclass ConsoleApp4.Program/Teacher
IL_000d: stloc.1
IL_000e: ret
} // end of method Program::Main

会调用castclass 进行转换。

因为castclass 无法找到他们两个的转换方法(编写显示转换或者隐式转换的方法),他们也不是继承关系,所以会抛出异常。

但是也不要以为所以的强制转换就一定要编写啥编写显示转换或者隐式转换的方法或者是啥继承关系,还有一种是编译器行为。

比如说:

long a = 1;
int b = (int)a;

编译出来的代码是:

IL_000d: stloc.1
IL_000e: ldc.i4.1
IL_000f: conv.i8
IL_0010: stloc.2
IL_0011: ldloc.2
IL_0012: conv.i4
IL_0013: stloc.3

这就是编译器的行为了,编译器认为自己可以处理就不报错了,直接截断作为处理了。

好吧,不能走的太远了,回到is 上。

那么is就可以避免一些运行时候的报错,而不需要用try catch 这种不太优雅的方式。

但是呢,is 是无法去检查自己编写的显示转换或隐式转换的方法,请看VAR:

class Program
{
static void Main(string[] args)
{
object obj = new Student();
if (obj is Teacher)
{
var c = (Teacher)obj;
}
} public class Student
{ } public class Teacher
{
}
}

编译出来呢?是下面这样:

.method private hidebysig static
void Main (
string[] args
) cil managed
{
.custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
01 00 01 00 00
)
// Method begins at RVA 0x20a4
// Header size: 12
// Code size: 30 (0x1e)
.maxstack 2
.entrypoint
.locals init (
[0] object obj,
[1] bool,
[2] class ConsoleApp4.Program/Teacher c
) IL_0000: nop
IL_0001: newobj instance void ConsoleApp4.Program/Student::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: isinst ConsoleApp4.Program/Teacher
IL_000d: ldnull
IL_000e: cgt.un
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: brfalse.s IL_001d IL_0014: nop
IL_0015: ldloc.0
IL_0016: castclass ConsoleApp4.Program/Teacher
IL_001b: stloc.2
IL_001c: nop IL_001d: ret
} // end of method Program::Main

is 转换为il代码就是isinst

这个只能判断继承关系,所以嘛,这个呢,其实也能理解,如果是自己编写了转换方法,哪里自己不知道还要is呢。

那么为啥会出现as呢?

还是性能问题嘛。

v1:

static void Main(string[] args)
{
object obj = new Student();
if (obj is Teacher)
{
var c = (Teacher)obj;
}
}

v2:

static void Main(string[] args)
{
object obj = new Student();
var c = obj as Teacher;
} public class Student
{ } public class Teacher
{
}

这两者有啥区别呢?道理上运行结果都一致。

但是呢,v2 更优,因为v2检查了一次,而v1检查来了两次。

v2的il代码:

.method private hidebysig static
void Main (
string[] args
) cil managed
{
.custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
01 00 01 00 00
)
// Method begins at RVA 0x20a4
// Header size: 12
// Code size: 15 (0xf)
.maxstack 1
.entrypoint
.locals init (
[0] object obj,
[1] class ConsoleApp4.Program/Teacher c
) IL_0000: nop
IL_0001: newobj instance void ConsoleApp4.Program/Student::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: isinst ConsoleApp4.Program/Teacher
IL_000d: stloc.1
IL_000e: ret
} // end of method Program::Main

这里也是使用了isinst,因为isinst本身就是检测并且赋值,再来看下isinst的功效

as 只是运行了stloc.1,弹出赋值给局部变量,多了一个赋值过程,两者性能都差不多,所以呢,不要觉得as 好像多比 is 多个一个转换啥的,其实调用的是同一个语句。

只是觉得以前写的过于潦草,整理下罢了。操作系统篇马上就要出炉,比较生硬,共128篇,简单整理一下。

c# is 和 as 浅看重制版的更多相关文章

  1. 浅谈Unity的渲染优化(1): 性能分析和瓶颈判断(上篇)

    http://www.taidous.com/article-667-1.html 前言 首先,这个系列文章做个大致的介绍,题目"浅谈Unity",因为公司和国内大部分3D手游开发 ...

  2. springboot开发浅谈 2021/05/11

    学习了这么久,本人希望有时间能分享一下,这才写下这篇浅谈,谈谈软件,散散心情. 这是本人的博客园账号,欢迎关注,一起学习. 一开始学习springboot,看了好多网站,搜了好多课程.零零落落学了一些 ...

  3. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  4. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  5. 【uwp】浅谈China Daily 中划词翻译的实现

    学习uwp开发也有一段时间了,最近上架了一个小应用(China Daily),现在准备将开发中所学到的一些东西拿出来跟大家分享交流一下. 先给出应用的下载链接:China Daily , 感兴趣的童鞋 ...

  6. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  7. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  8. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  9. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  10. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

随机推荐

  1. CSS & JS Effect – Virtual Scrolling

    前言 我正在写 Angular CDK Scrolling 教程,它里面有一个 Virtual Scrolling 功能.借此机会,我想顺便写一篇纯 Sass & TS 的版本作为学习. Vi ...

  2. 「模拟赛」A 层多校联训 4(卖品:CTH)

    双倒一啦! 感觉这次最大的错误就是没看 T2.(本质原因还是时间浪费的太多了) 赛时记录在闲话啦 accoder 多校比赛链接 02 表示法 唐诗题!考高精的人都\(**\),输出深度优先搜索解决.高 ...

  3. 三维医学图像数据扩充:flip and rotate

    对于小数据量医学图像进行深度学习使,会由于数据量过小而过拟合.因此我们需要采用数据扩充方法,而flip和rotate又是经常用到的,这里做一个简单的实现. 输入为[batchsize,height, ...

  4. 基于Python后端构建多种不同的系统终端界面研究

    在我们一般开发系统的时候,往往会根据实际需要做出各种不同的系统终端界面,如基于BS的,CS.APP.小程序等等,一般都是基于一个统一接入的Web API后端,本篇系统探寻对基于Python后端构建多种 ...

  5. iOS 数据持久化方案-Realm的使用小结

    一.Realm介绍 1.1.Realm是一个跨平台移动数据库引擎,支持iOS.OS X(Objective-C和Swift)以及Android,核心数据引擎C++打造,并不是建立在SQLite之上的O ...

  6. 深入探索Spring AI:源码分析流式回答

    在上一章节中,我们深入分析了Spring AI的阻塞式请求与响应机制,并探讨了如何增强其记忆能力.今天,我们将重点讲解流式响应的概念与实现.毕竟,AI的流式回答功能与其交互体验密切相关,是提升用户满意 ...

  7. C++第七节课 new开辟空间 delete释放空间

    #include <iostream> using namespace std; // C中开辟空间的方式 所有的返回值 都是 void * /// int * p = (int*)mal ...

  8. C#的引用类型

    引用类型的基类为 Object 引用类型:类Class.接口Interface.委Delegrate.数组Array

  9. ⼯作⾥中的token是怎么管理的?

    我们公司的token管理都是通过vuex配合本地存储来做的,使⽤vuex是因为token数据⽐较特殊,在很多 模块中都可能会⽤到,vuex⽅便管理,配合本地存储⽐如localstorage,是因为vu ...

  10. Centos7下非lvm的分区扩容

    Centos7下非lvm的分区扩容(重要) 前言:一般在生产环境中,如果需要使用一个分区保存大量的文件,建议的做法是在虚拟化环境中增加一块单独的硬盘,挂载一个单独的分区,比如 /data 上图我们可以 ...