谈谈值类型与null的判等比较!
如果一个值类型没有重载==运算符,是无法直接使用==来进行值类型的实例和null的判等比较的,这个是显而易见的,默认情况下值类型都没有重载==运算符:
A a;
if(a==null) //
struct A
{
public int x;
}
但是,是否重载了==就可以把值类型的实例和null做判等比较了呢?现在,我们来看一个更加能说明问题的Demo:
using System;这里重载了==运算符就使得myStuct2==null通过了编译,情况似乎有些诡异,因为貌似==两边的类型无法匹配重载的定义!
namespace StructOperatorDemo
{
class Program
{
public struct MyStruct1
{
public Guid UniqueId;
public MyStruct1(Guid fUniqueId)
{
this.UniqueId = fUniqueId;
}
}
public struct MyStruct2
{
public int Value;
public MyStruct2(int fValue)
{
this.Value = fValue;
}
public static bool operator !=(MyStruct2 s1, MyStruct2 s2)
{
return s1.Value != s2.Value;
}
public static bool operator ==(MyStruct2 s1, MyStruct2 s2)
{
return s1.Value == s2.Value;
}
public override int GetHashCode()
{
return this.Value;
}
}
static void Main(string[] args)
{
// 错误: 运算符“==”无法应用于 “MyStruct1” 和 “<null>” 类型
// MyStruct1 myStruct1 = new MyStruct1();
// if (myStruct1 == null)
// {
// }
// 正确
MyStruct2 myStruct2;
if (myStruct2 == null)
{
Console.WriteLine("myStruct2==null");
}
}
}
}
首先,我们尝试在==运算符重载方法中加断点,结果观察到里面的代码并没有执行。
自从.NET Framework2.0引入了可空类型,只要你定义了==运算符重载(两个参数类型必须都是原类型才可以),这里C#编译器会认可这个判等表达式,由于 一个值类型的实例永远不可能等于可空类型的null,所以这里C#编译器智能的认为这个判等表达式永远为false,我们来看看Main方法的IL
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 9 (0x9)
.maxstack 2
.locals init ([0] valuetype ConsoleApplication1.MyStruct2 myStruct2,
[1] bool CS$4$0000)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: ldc.i4.0
IL_0003: ceq //这里比较的是0和0,这个行为很有趣,==结果是固定的情况下就比较0和0,!=结果固定的情况下比较的是0和1
IL_0005: stloc.1 //比较结果放入临时变量CS$4$0000中,但是以后根本就不使用了!
IL_0006: br.s IL_0008 //无条件跳转,if里的代码并没有生成IL
IL_0008: ret
} // end of method Program::Main
这里值类型和null的判等比较只有当重载==运算符,并且两个参数类型必须都是原类型才可以,比如我们这样修改重载方法:
public static bool operator ==(MyStruct2 s1, MyStruct1 s2) //修改第二个参数类型这样会出现编译错误了:运算符“==”无法应用于 “MyStruct1” 和 “<null>” 类型
{
return s1.Value == s2.GetHashCode();
}
实际上由于值类型和null的比较结果是一定的,所以也没有必要做判等比较,这里只是观察一下C#编译器的一些行为,希望把一些有趣的现象分享给大家!
希望大家多多指教啊!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?