c# is 和 as 浅看重制版
前言
当年写的比较差: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 浅看重制版的更多相关文章
- 浅谈Unity的渲染优化(1): 性能分析和瓶颈判断(上篇)
http://www.taidous.com/article-667-1.html 前言 首先,这个系列文章做个大致的介绍,题目"浅谈Unity",因为公司和国内大部分3D手游开发 ...
- springboot开发浅谈 2021/05/11
学习了这么久,本人希望有时间能分享一下,这才写下这篇浅谈,谈谈软件,散散心情. 这是本人的博客园账号,欢迎关注,一起学习. 一开始学习springboot,看了好多网站,搜了好多课程.零零落落学了一些 ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈 LayoutInflater
浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...
- 【uwp】浅谈China Daily 中划词翻译的实现
学习uwp开发也有一段时间了,最近上架了一个小应用(China Daily),现在准备将开发中所学到的一些东西拿出来跟大家分享交流一下. 先给出应用的下载链接:China Daily , 感兴趣的童鞋 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈SQL注入风险 - 一个Login拿下Server
前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- 浅谈angular2+ionic2
浅谈angular2+ionic2 前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别. 1. 项目所用:angular2+ionic2 ...
- iOS开发之浅谈MVVM的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
随机推荐
- python学习教材选哪个
python语言俨然成为当今最流行的国际语言,无论你是做AI的还是非AI,大家都在用python语言,各种平台也都开始支持python,现在连文科生都在学习python语言了,甚至很多表哥表姐的工作都 ...
- JavaScript – Proxy
参考 阮一峰 – Proxy 介绍和使用 Proxy 的作用是代理对象, 消费者不直接使用对象, 而是使用代理对象. 一般上做代理的目的就是想拦截对象访问做一些别的事情. 比如当对象改变以后, 同步 ...
- 火山引擎数智平台:高性能ChatBI的技术解读和落地实践
导读:大模型能力的发展和成熟,催生出新一代智能化 BI-- ChatBI,即通过自然语言处理(NLP)与大型语言模型(LLMs)的结合,极大简化数据分析过程,提高效率并降低分析门槛.火山引擎数智平台旗 ...
- element plus 2.3.14(完成 指南 部分)
https://element-plus.org/zh-CN/guide/design.html 设计 控制反馈: 通过界面样式和交互动效让用户可以清晰的感知自己的操作: 页面反馈: 操作后,通过页面 ...
- QT6跨平台开发
QT6跨平台开发 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C++扩展开发视频课程 免费QT视频课程 您可以看免费1000+个QT技术 ...
- QT QML实用效果之实现页面切换效果
简介 本文介绍了如何使用QT QML和JavaScript实现页面动态加载和切换的效果. 文章目录 效果 JavaScript代码:butianyun.js文件 QML代码:主页面 页面A QML代码 ...
- 深入C++引用及其注意事项、对引用取地址时的内存模型、const数组等
const int f[10] = { 1,2,3,4,5,6,7,8,9,10 }; int main() { // test1 const int i = 3; int& j = cons ...
- 2024 ByteCTF
ByteCTF 极限逃脱 题目描述:本题需要通过动态调试分析出要输入的内容,可能在某些地方会有提示出现. 这是一个IOS逆向,因为没有设备只能静态分析 流程和安卓逆向大概一致 解压拖进ida 提示输入 ...
- linux中安装mysq5.7
linux中安装mysq5.7 一. 安装mysql yum install mariadb-server mariadb 二. 开启mysql service mysqld start 四. 停止m ...
- src 和 href 的区别?
src:都是引用资源 src:指向外部资源的位置 , 当浏览器解析到此元素时,会暂停其它资源的下载和处理 , 直到将该资源加载 , 编译 , 执行完毕 ,相当于将资源嵌入到文档中当前元素的所在的位置: ...