c# is 和 as 浅看重制版

news/2024/11/30 20:20:30/文章来源:https://www.cnblogs.com/aoximin/p/18572890

前言

当年写的比较差: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: nopIL_0001: newobj instance void ConsoleApp4.Program/Student::.ctor()IL_0006: stloc.0IL_0007: ldloc.0IL_0008: castclass ConsoleApp4.Program/TeacherIL_000d: stloc.1IL_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: nopIL_0001: newobj instance void ConsoleApp4.Program/Student::.ctor()IL_0006: stloc.0IL_0007: ldloc.0IL_0008: isinst ConsoleApp4.Program/TeacherIL_000d: ldnullIL_000e: cgt.unIL_0010: stloc.1IL_0011: ldloc.1IL_0012: brfalse.s IL_001dIL_0014: nopIL_0015: ldloc.0IL_0016: castclass ConsoleApp4.Program/TeacherIL_001b: stloc.2IL_001c: nopIL_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: nopIL_0001: newobj instance void ConsoleApp4.Program/Student::.ctor()IL_0006: stloc.0IL_0007: ldloc.0IL_0008: isinst ConsoleApp4.Program/TeacherIL_000d: stloc.1IL_000e: ret
} // end of method Program::Main

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/844250.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20222422 2024-2025-1 《网络与系统攻防技术》实验五实验报告

一、实验内容 (1)从www.besti.edu.cn、baidu.com、sina.com.cn中选择一个DNS域名进行查询,获取如下信息: DNS注册人及联系方式 该域名对应IP地址 IP地址注册人及联系方式 IP地址所在国家、城市和具体地理位置 PS:使用whois、dig、nslookup、traceroute、以及各类在线和离线…

安装扫描仪DS-410出现安装Desktop Experience提示

安装Epson Scan所需的某些模块没有安装。安装Desktop Experience之后安装Epson Scan。在Windows server 2012上安装扫描仪出现该错误,该错误为server系统需要桌面支持,默认Windows server 该功能是不安装的需要用户按需求安装。 安装windows server 2012 R2 安装桌面体验勾选…

2019-8-29-02-JS-DOM

图片轮播是Web开发中最常见的组件之一,这是一篇用原生JavaScript实现简单图片轮播的教程。 要实现图片轮播,首先我们要将图片轮播拆分为图片容器、图片、上一页按钮、下一页按钮、底部点选容器、底部点选按钮。 下面我们用HTML代码表示。 ... <div id="page">…

【朝花夕拾】蓝牙WiFi常识篇

一、蓝牙常识点 1、常见英文缩写缩写 英文全称 释义BLE Bluetooth Low Energy低功耗蓝牙BR Basic Rate基本速率,一般说的经典蓝牙就是指BR/EDREDR Enhanced Data Rate增强速率,BR的增强版,一般说的经典蓝牙就是指BR/EDRBluetooth SIG Bluetooth Special Interest Group蓝牙技…

Git入门图文教程(1.5W字40图)--深入浅出、图文并茂

原文:Git入门图文教程(1.5W字40图)🔥🔥--深入浅出、图文并茂 - 安木夕 - 博客园01、认识一下Git!—简介 Git是当前最先进、最主流的分布式版本控制系统,免费、开源!核心能力就是版本控制。再具体一点,就是面向代码文件的版本控制,代码的任何修改历史都会被记录管理起…

20222414 2024-2025-1 《网络与系统攻防技术》实验七实验报告

1.实验内容及要求 1.1本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法。具体实践有 (1)简单应用SET工具建立冒名网站 (2)ettercap DNS spoof (3)结合应用两种技术,用DNS spoof引导特定访问到冒名网站。 1.2本周学习内容 (1)web安全基础:…

硬盘的基本知识与选购指南

1、3.5和2.5英寸硬盘的英寸,不是指外壳的尺寸,而是硬盘盘片的直径尺寸。 无论是 2.5英寸的硬盘还是 3.5 英寸的硬盘,都是使用 SATA 接口。 1.1、3.5英寸 3.5 英寸的硬盘在 1984 年就已经诞生,直到在 1991 年出现首款容量为 1GB 的机械硬盘,3.5 英寸硬盘开始成为标准规格。…

《Django 5 By Example》阅读笔记:p455-p492

《Django 5 By Example》学习第 16 天,p455-p492 总结,总计 38 页。 一、技术总结 1.myshop (1)打折功能 使用折扣码实现,但是折扣码是手动生成的,感觉实际业务中应该不是这样的。 (2)推荐功能 使用 Redis 做缓存,结合商品的销量做推荐,算是一种普通的实现方案。 二、英语…

[ctf]跟着风二西复现NSSCTF流量题目

题目参考博客 https://blog.csdn.net/zerorzeror/article/details/135737476?spm=1001.2014.3001.5502 20241130 [GKCTF 2021]签到 解题过程 可以看到流量并不多,看到GET和POST里面有tmpshell 然后追踪HTTP流 可以看到初始的这一段字符,因为字符中字母最大的为f,无其他字符…

STM2F411智能手环设计

最近闲来无事就想制作一款智能手表,为此我直接从网上找到一个开源项目OV-Watch。这里我们就以这个开源项目为例,一步步就讲解,从最初的电路原理图绘制,到PCB打样焊接,到最后的程序编写烧录测试。 由于该开源项目包含了若干个版本,这里我们在复刻的时候以当前最新版本为例…

强烈推荐!终于找到了一个查看 dotnet 源码的便捷方法

强烈推荐!终于找到了一个查看 dotnet 源码的便捷方法 快把这个网站加入标签栏 “https://source.dot.net/” ​​ 为什么推荐由GitHub生成,由Roslyn提供支持。 不需要梯子,快速访问如何使用 1、查找类型和成员声明、文件和程序集:搜索内容 示例完整或部分类型或成员名称。字…

20222406 2024-2025-2 《网络与系统攻防技术》实验七实验报告

20222406 2024-2025-2 《网络与系统攻防技术》实验七实验报告 1.实验内容应用 SET 工具,通过多步操作建立冒名网站,获取登录信息。 利用 ettercap 实施 DNS spoof 攻击,篡改特定网站 IP。 结合两种技术,用 DNS spoof 引导访问至冒名网站。2.实验过程 2.1 简单应用SET工具建…