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的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
随机推荐
- MVC @Html.TextBox 属性
MVC中设置文本框不可修改(@Html.TextBox) mvc前台: @Html.TextBox("id","name", new {@Readonly = ...
- Nuxt Kit 的使用指南:从加载到构建
title: Nuxt Kit 的使用指南:从加载到构建 date: 2024/9/12 updated: 2024/9/12 author: cmdragon excerpt: 摘要:本文详细介绍了 ...
- Angular 18+ 高级教程 – Animation 动画
前言 Angular 有一套 built-in 的 Animation 方案.这套方案的底层实现是基于游览器原生的 Web Animation API. CSS Transition -> CS ...
- HTTP——响应数据格式
HTTP响应数据格式 状态码分类: 常见的状态响应码:
- 如何判断一个网站是用的Nginx,还是Apache
事件起因: 接手了同事移交过来的一个网站,但是不知道这个网站是用什么做代理的,于是就去网上查资料 解决办法: 打开cmd窗口,输入以下命令即可 curl --head 域名/IP 注意,--hea ...
- PHP面试,Redis
1. 什么是Redis? Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,它可以用作数据库.缓存和消息中间件.它支持多种数据结构,如字符串.哈希.列表.集合 ...
- C++中指针和数组相关的运算符优先级
概述 本文深入介绍了与指针和数组相关的运算符优先级,利用代码示例展示了当左结合和右结合运算符同时存在时的结合方式,同时也演示了如何使用()来强制人为指定结合顺序. 指针.数组相关的运算符优先级 下表展 ...
- UsbHostManager解析
UsbHostManager和UsbDeviceManager的区别在于,UsbDeviceManager是将手机作为一个设备,比如手机连上电脑,使用adb.mtp等:而UsbHostManager, ...
- 对于ChannelNet的一点理解
主要是为了个人理解,做个笔记 1.Pytorch代码 2.论文出处 3.详细介绍 这篇论文在2018年发出来,而ShuffleNet是从2017年由旷视发出来.起初了解shufflenet的提出,主要 ...
- iOS多态使用小结
多态是面试程序设计(OOP)一个重要特征,但在iOS中,可能比较少的人会留意这个特征,实际上在开发中我们可能已经不经意的使用了多态.比如说: 有一个tableView,它有多种cell,cell的UI ...