C# 类型转换核心概念总结
🔄 一、两大转换类型(核心区分)
1. 隐式转换(Implicit Conversion)
编译器自动完成,无需代码干预,保证数据安全
csharp
// 值类型:小转大(安全)
int a = 100;
double b = a; // ✅ 自动转换,无数据丢失
// 引用类型:子类转父类(安全)
父类 obj = new 子类(); // ✅ 子类对象可以赋值给父类变量
规则:
-
值类型:小范围 → 大范围(int→long, float→double)
-
引用类型:子类 → 父类
-
绝对安全:不会丢失数据或信息
2. 显式转换(Explicit Conversion)
程序员手动写代码,可能数据丢失,需要谨慎
csharp
// 值类型:大转小(危险)
double d = 123.456;
int i = (int)d; // 需要显式转换,丢失小数部分
// 引用类型:父类转子类(危险)
父类 obj = new 子类();
子类 child = (子类)obj; // 需要显式转换
特点:
-
需要强制类型转换符 :
(目标类型) -
可能数据丢失 或运行时异常
-
程序员必须明确知道转换是安全的
⚠️ 二、引用类型转换的特殊性
继承关系是转换的基础
csharp
public class 父类 { }
public class 子类 : 父类 { } // 子类继承父类
// ✅ 隐式:子→父(总是安全)
父类 parent = new 子类();
// ⚠️ 显式:父→子(可能失败)
子类 child = (子类)parent; // 仅当parent实际是子类对象时才安全
🛡️ 三、安全转换技术
1. as 运算符(最安全)
csharp
父类 obj = new 父类();
子类 result = obj as 子类; // 尝试转换
if (result != null) // 转换成功
{
// 安全使用
}
// 失败时返回 null,不会抛出异常
特点:
-
失败返回
null,不会抛异常 -
只能用于引用类型
-
推荐用于引用类型转换
2. is 运算符 + 模式匹配
csharp
// 传统方式
if (obj is 子类)
{
子类 child = (子类)obj; // 需要两次操作
}
// 模式匹配(C# 7.0+)
if (obj is 子类 child) // 判断并转换一步完成
{
// 可以直接使用 child
}
特点:
-
返回
bool,不会抛异常 -
可用于所有类型(值类型+引用类型)
-
模式匹配语法更简洁
📊 四、as vs is 对比表
| 特性 | as 运算符 | is 运算符 |
|---|---|---|
| 返回值 | 成功:目标类型对象 失败:null |
成功:true 失败:false |
| 异常 | 永远不会抛出异常 | 永远不会抛出异常 |
| 适用类型 | 仅引用类型 | 所有类型 |
| 代码简洁度 | 需要额外判空 | 模式匹配时简洁 |
| 性能 | 较快 | 稍慢(需类型检查) |
🔧 五、其他转换方式
Parse 方法(字符串→其他类型)
csharp
// 字符串转数值
int num = int.Parse("123"); // 失败抛异常
bool success = int.TryParse("abc", out int result); // 安全版本
// 使用场景:用户输入、配置文件读取
Convert 类(万能转换)
csharp
// 更强大的转换功能
double d = Convert.ToDouble("123.45");
int i = Convert.ToInt32(123.456); // 四舍五入
// 特点:处理 null、支持更多类型转换
自定义转换(操作符重载)
csharp
public class MyClass
{
public int Value { get; set; }
// 隐式转换操作符
public static implicit operator int(MyClass obj)
=> obj.Value;
// 显式转换操作符
public static explicit operator MyClass(int value)
=> new MyClass { Value = value };
}
🎯 六、选择指南(实战决策)
什么情况用什么?
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 字符串转数值 | TryParse() |
安全,避免异常 |
| 引用类型向下转换 | as 运算符 |
安全,代码简洁 |
| 类型检查+转换 | is 模式匹配 |
一步完成 |
| 数值大转小 | 显式转换 (int) |
明确表达意图 |
| 复杂类型转换 | Convert 类 |
功能全面 |
💡 七、重要原则(必须记住)
黄金法则:
-
隐式转换:编译器帮你,绝对安全
-
显式转换:你告诉编译器"我知道风险"
-
as/is:安全第一,避免崩溃
安全优先级:
text
TryParse() > as/is > 显式转换 > Parse()
常见陷阱:
csharp
// ❌ 危险:可能抛出 InvalidCastException
子类 obj = (子类)某个父类对象;
// ✅ 安全:使用 as 或 is
子类 obj = 某个父类对象 as 子类;
if (obj != null) { /* 安全使用 */ }
📝 八、一句话记忆
-
隐式转换:自动的、安全的(小→大,子→父)
-
显式转换:手动的、有风险的(大→小,父→子)
-
as 转换:安全的引用类型转换(失败返回null)
-
is 检查:安全的类型检查(可结合转换)
🚨 九、警告清单
绝对不要这样做:
-
不检查就直接显式转换父类为子类
-
使用
Parse()而不考虑异常 -
忽略
as转换的null检查 -
在有符号和无符号类型间随意转换
应该这样做:
-
优先使用
as和is -
字符串转数值用
TryParse() -
不确定时先检查再转换
-
明确转换可能的数据丢失