当前位置: 首页 > news >正文

C#强制类型转换(显示转换)和安全类型转换

目录

强制类型转换(显式转换)

1.核心特性

2. 适用场景

2.1.值类型之间的兼容转换

2.2.引用类型的“继承链转换”

2.3.object与其他类型的转换

安全类型转换

1.as关键字:尝试转换,失败返回null

1.1.核心特性

1.2.适用场景

1.2.1.引用类型的安全转换

1.2.2.可空值类型的安全转换

2. is 关键字:先判断兼容性,再转换

2.1.核心特性

2.2.适用场景

2.2.1.值类型的安全转换

2.2.2.引用类型的安全转换(替代as)

2.2.3.复杂类型的多分支判断

强制转换 vs 安全转换

什么时候用哪种转换?

常见错误与避坑


       本篇文章来分享一下C#的强制类型转换和安全类型转换,强制类型转换也称为显示转换。在C#中,类型转换是将一种数据类型的值转换为另一种数据类型的操作,核心分为强制类型转换(显式转换)和安全类型转换(as关键字、is关键字)两类。

强制类型转换(显式转换)

       强制类型转换是开发者确认两种类型可兼容的转换方式。它直接对值进行类型转换,若转换不合法会立即抛出异常。

1.核心特性

(1)语法:目标类型 变量名 = (目标类型)源值;

(2)转换逻辑:直接操作内存中数据的类型标识(或值的格式),要求两种类型在编译期/运行期具备“可转换关系”(如继承、值类型兼容)。

(3)错误处理:若转换不合法(如将string转int、将父类实例转子类),立即抛出InvalidCastException异常,中断程序执行(未捕获时)。

(4)适用范围:支持值类型(如int→long)和引用类型(如object→string、子类→父类)。

2. 适用场景

       强制转换并非“任意类型都能转”,仅支持以下合法场景:

2.1.值类型之间的兼容转换

       当两种值类型具备“范围包含”或“格式兼容”关系时,可强制转换,可能丢失精度

(1)范围窄→范围宽(隐式转换也支持,强制转换可显式声明):

       如 int(4 字节)→long(8 字节)、float→double,转换安全无精度丢失。

int num1 = 100;
long num2 = (long)num1;//合法,也可省略 (long) ,隐式转换

(2)范围宽→范围窄(必须强制转换,可能丢失精度):

       如long→int、double→float,若源值超出目标类型范围,会导致“溢出”(默认不抛异常,仅返回错误值;开启溢出检查后抛OverflowException)。

long bigNum = 2147483648;//超出 int 最大值(2^31 - 1=2147483647)
int smallNum = (int)bigNum;//溢出,smallNum 结果为2147483648 - 2^32 = -2147483648,错误值

2.2.引用类型的“继承链转换”

       父类实例→子类实例,必须强制转换,且运行期需确保父类实例本质是子类对象,父类引用可指向子类对象(多态),但需强制转换才能调用子类特有成员。

public class Animal { }
public class Dog : Animal
{public void Bark(){Debug.Log("小狗汪汪~");}
}
public class Test : MonoBehaviour
{public void Start(){Animal animal = new Dog();//多态:父类引用指向子类对象Dog dog = (Dog)animal;//合法:强制转换后可调用 Bark()dog.Bark();//执行成功}
}

       若父类实例不是子类对象,强制转换会抛 InvalidCastException:

Animal animal = new Animal();//父类实例
Dog dog = (Dog)animal;//运行期抛异常:无法将 Animal 转换为 Dog

2.3.object与其他类型的转换

       object是所有类型的基类,其他类型与object之间可强制转换。

其他类型与object之间的转换包括装箱和拆箱:

1.装箱:值类型→object,支持隐式转换,也可强制转换。

2.拆箱:object→值类型,必须强制转换,且object中存储的必须是目标值类型(否则抛 InvalidCastException)。

//装箱:int→object
int num = 10;
object obj = (object)num;//合法,也可省略 (object) 隐式装箱//拆箱:object→int(必须强制转换)
int num2 = (int)obj;//合法,obj 中存储的是 int//错误拆箱:obj 中存储的是 int,转 string 抛异常
string str = (string)obj;//运行期抛异常:无法将 int 转换为 string

安全类型转换

       安全类型转换是开发者不确定类型是否兼容,希望避免异常的转换方式,依赖as关键字(直接转换)和is关键字(先判断再转换)。

1.as关键字:尝试转换,失败返回null

1.1.核心特性

(1)语法:目标类型 变量名 = 源值 as 目标类型;

(2)转换逻辑:尝试将源值转换为目标类型,若兼容则返回转换后的值;若不兼容则返回null(不抛异常)。

(3)关键限制:仅支持引用类型(如class、interface、string)和可空值类型(如int?、double?);不支持非可空值类型(如 int、float),若用于非可空值类型会编译报错。

(4)错误处理:转换失败时返回null,需通过if(变量名 == null) 判断结果。

1.2.适用场景

1.2.1.引用类型的安全转换

       替代 “可能失败的强制转换”,避免异常:

public class Animal { }
public class Dog : Animal 
{ public void Bark() { Debug.Log("小狗汪汪~");} 
}
public class Cat : Animal 
{ public void Meow() {Debug.Log("小猫喵喵~");} 
}
public class Test : MonoBehaviour
{public void Start(){Animal animal = new Dog();//父类引用指向 Dog 实例//用 as 转换为 Dog(兼容,返回 Dog 实例)Dog dog = animal as Dog;if (dog != null){dog.Bark();//执行成功}//用 as 转换为 Cat(不兼容,返回 null)Cat cat = animal as Cat;if (cat != null){cat.Meow();//条件不满足,不执行}}
}

1.2.2.可空值类型的安全转换

       非可空值类型需先包装为可空值类型,才能用 as 转换:

object obj = 10;//obj中存储的是 int//错误:非可空值类型 int 不能用 as 转换(编译报错)
//int num = obj as int;//正确:用可空值类型 int? 转换
int? num = obj as int?;
if (num != null)
{Console.WriteLine(num); //输出:10
}//转换失败:obj 中是 int,转 double? 返回 null
double? dNum = obj as double?;
if (dNum == null)
{Console.WriteLine("转换失败");//输出:转换失败
}

2. is 关键字:先判断兼容性,再转换

       is 关键字本身不执行转换,仅判断源值是否兼容于目标类型,返回bool值(true/false)。通常与模式匹配结合,实现“判断 + 转换”一步完成,比as更直观。

2.1.核心特性

(1)语法

基础判断:bool 兼容 = 源值 is 目标类型;

模式匹配(判断 + 转换):if (源值 is 目标类型 变量名)

(2)转换逻辑:先判断源值是否兼容于目标类型(运行期检查);若兼容,自动将源值转换为目标类型并赋值给变量(无需额外强制转换);若不兼容,不执行后续逻辑(不抛异常)。

(3)适用范围:支持所有类型(值类型、引用类型、可空值类型),无as的类型限制。

2.2.适用场景

2.2.1.值类型的安全转换

       as不支持非可空值类型,is可完美解决:

object obj = 100;
//用 is 判断并转换为 int(非可空值类型)
if (obj is int num)
{Console.WriteLine(num + 50);//输出:150(转换成功,直接使用num)
}//用 is 判断并转换为 double(不兼容,不执行)
if (obj is double dNum)
{Console.WriteLine(dNum);//不执行
}

2.2.2.引用类型的安全转换(替代as)

       相比as,is模式匹配无需手动判断null,代码更简洁:

Animal animal = new Cat();//用 is 模式匹配:判断是否为 Cat,若是则自动转换为 cat 变量
if (animal is Cat cat)
{cat.Meow();//执行成功
}//用 is 模式匹配:判断是否为 Dog,若不是则不执行
if (animal is Dog dog)
{dog.Bark();//不执行
}

2.2.3.复杂类型的多分支判断

       在多类型分支场景中,is模式匹配比as更易读:

public class Animal { }
public class Dog : Animal 
{ public void Bark() { Debug.Log("小狗汪汪~");} 
}
public class Cat : Animal 
{ public void Meow() {Debug.Log("小猫喵喵~");} 
}
public class Bird : Animal
{public void Sing(){Debug.Log("小鸟吱吱~");}
}
public class Test : MonoBehaviour
{public void Start(){AnimalSound(new Dog());//Bark 执行AnimalSound(new Bird());//Sing 执行}private void AnimalSound(Animal animal){if (animal is Dog dog){dog.Bark();}else if (animal is Cat cat){cat.Meow();}else if (animal is Bird bird){bird.Sing();}else{Console.WriteLine("未知动物");}}
}

强制转换 vs 安全转换

维度

强制类型转换 (T)obj

安全类型转换(as/is)

语法

(目标类型)源值

as:源值 as 目标类型

is:源值 is 目标类型 变量

错误处理

不兼容时抛InvalidCastException

as:返回 null

is:不执行逻辑(均不抛异常)

支持类型

所有类型(值类型、引用类型)

as:引用类型/可空值类型;

is:所有类型

适用场景

确定类型兼容,需即时暴露错误

不确定类型兼容,需避免异常

性能

无额外开销(直接转换)

as:无额外开销

is:仅多一次类型判断(可忽略)

代码健壮性

低(异常可能中断程序)

高(容错性强,错误可显式处理)

什么时候用哪种转换?

1.优先用is模式匹配

场景:不确定类型兼容、需要多分支判断、转换值类型时;

理由:代码简洁、无异常风险、支持所有类型。

2.其次用as关键字

场景:仅需单次引用类型转换,且需用null判断结果时;

理由:比is少一次类型判断(理论性能略优),但需手动处理null。

3.最后用强制转换 (T)

场景:100%确定类型兼容(如单例模式中反射获取的实例、父类引用明确指向子类对象);

理由:无额外开销,且能即时暴露错误(若代码逻辑出错,强制转换抛异常便于调试);

禁忌:避免在可能不兼容的场景中使用(如用户输入、动态数据转换),否则易引发未捕获异常。

常见错误与避坑

1.非可空值类型用 as 转换:编译报错,需改用 is 或强制转换。

//错误:int 是非可空值类型,不能用 as
int num = obj as int;//正确:用 is 模式匹配
if (obj is int num) { }

2.强制转换父类实例为子类:若父类实例不是子类对象,运行期抛异常,需先判断(用is)。

Animal animal = new Animal();
//错误:animal 不是 Dog 实例,强制转换抛异常
Dog dog = (Dog)animal;//正确:先判断再转换
if (animal is Dog dog) { }

3.as转换后不判断null:直接使用可能抛NullReferenceException,需先检查null。

Dog dog = animal as Dog;
//错误:若 dog 是 null,调用 Bark() 抛空引用异常
dog.Bark();//正确:先判断 null
if (dog != null) 
{ dog.Bark(); 
}

       好了,本次的分享到这里就结束啦,希望对你有所帮助~


文章转载自:

http://2iyV37IX.hwcLn.cn
http://CItsMbQm.hwcLn.cn
http://BaOxWkXI.hwcLn.cn
http://uKGleRba.hwcLn.cn
http://r20sZLSb.hwcLn.cn
http://wHl4ApEu.hwcLn.cn
http://5ZUKUhCi.hwcLn.cn
http://lyEPKXyB.hwcLn.cn
http://zVEy4azO.hwcLn.cn
http://kajxdfmh.hwcLn.cn
http://znFxXYJL.hwcLn.cn
http://eMBQhCuT.hwcLn.cn
http://LRfKEyJL.hwcLn.cn
http://GstlZlNx.hwcLn.cn
http://Yh6D7Ciq.hwcLn.cn
http://TFeV1zOj.hwcLn.cn
http://RZPxjJKE.hwcLn.cn
http://w1iFEwgj.hwcLn.cn
http://zQ1y1LoJ.hwcLn.cn
http://Jdf2t5of.hwcLn.cn
http://GxuWLt6l.hwcLn.cn
http://Z8FSuDA4.hwcLn.cn
http://IRrc4kya.hwcLn.cn
http://X0wMzAJD.hwcLn.cn
http://aIfT9zty.hwcLn.cn
http://csx0pvLH.hwcLn.cn
http://943nekMi.hwcLn.cn
http://rHWG7EFo.hwcLn.cn
http://D80cwfH2.hwcLn.cn
http://9jXtnez5.hwcLn.cn
http://www.dtcms.com/a/366612.html

相关文章:

  • 激光频率梳 3D 轮廓测量 - 莫尔条纹光的工作原理及优缺点
  • 2025变现打法:AI+IP实现高效变现|创客匠人
  • Mysql杂志(九)
  • Agent Prompt工程:如何让智能体更“听话”?(实践指南)
  • 深度学习玩游戏, 模型玩游戏,大模型+游戏 llm+game, 机器学习玩游戏,人工智能游戏陪伴,模型陪玩游戏
  • 机器学习基础-day02-K近邻算法
  • 大数据框架Doris全面解析
  • 学习机器学习能看哪些书籍
  • 计算机毕业设计:基于Python的影评情感分析可视化推荐系统
  • 【嵌入式DIY实例-ESP32篇】-倾斜弹跳球游戏
  • 【CouponHub项目开发】使用RocketMQ5.x实现延时修改优惠券状态,并通过使用模板方法模式重构消息队列发送功能
  • Unity中,软遮罩SoftMaskForUGUI可移动遮罩形状实现方法
  • 阻抗、瞬时阻抗、特性阻抗的区别
  • AI重构出海营销:HeadAI如何用“滴滴模式”破解红人营销效率困局?
  • 元宇宙与教育变革:沉浸式学习重构知识获取与能力培养
  • 从关键词到语义理解:小陌引擎如何重构AI搜索优化逻辑?
  • 【RNN-LSTM-GRU】第三篇 LSTM门控机制详解:告别梯度消失,让神经网络拥有长期记忆
  • 《ConfigMap热更新失效的深度解剖与重构实践》
  • Java GcExcel V8.2 新版本:效率升级与功能突破
  • Excel ——INDEX + MATCH 组合
  • Loopback for Mac:一键打造虚拟音频矩阵,实现跨应用音频自由流转
  • Leetcode—3516. 找到最近的人【简单】
  • wps的excel如何转为谷歌在线表格
  • JAVA层的权限与SELinux的关系
  • 【Python基础】 14 Rust 与 Python 标识符命名规则与风格对比笔记
  • AI编程:重塑软件开发范式的三大支柱
  • 微信小程序-day4
  • AI安全必修课:模型偏见检测与缓解实战
  • STL重点
  • 云手机的稳定性会受到哪些因素的影响?