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

空值处理操作符

可空类型修饰符 

// 允许值类型接受null值  
public class NullableExample  
{  
    int normalInt = null;     // 编译错误!  
    int? nullableInt = null;  // 正确,可以接受null  
    
    DateTime? nullableDate = null;  // 正确  
    bool? nullableBool = null;      // 正确  

    public void Example()  
    {  
        if (nullableInt.HasValue)  // 检查是否有值  
        {  
            int value = nullableInt.Value;  // 获取实际值  
        }  
    }  
}  

概述 

当值类型使用?可空操作符时,它依然是值类型,只是被包装成了System.Nullable<T>结构体,并不会变成引用类型。

内存分配

值类型:直接在栈上分配
可空值类型:在栈上分配,但有额外的标志位
引用类型:在堆上分配,栈上存储引用

性能特征

值类型:最高性能
可空值类型:略有性能开销
引用类型:需要垃圾回收

功能特性

值类型:不能为null
可空值类型:可以为null,需要检查HasValue
引用类型:默认可以为null

应用场景

某些场景下,我们需要区分"未设置"(null)和"默认值"(如int的0)的情况。

这里还是不明白为什么使用可空作符。疑惑点是值类型有默认值,在游戏开发中我们可以根据默认值做判断处理,为什么还需要这个可空操作符呢?并且还会带来性能开销,内存增加的问题。

想取默认值吗?有点意思。那如果是DateTime结构体呢?它的默认值是 0001年1月1日 00:00:00当然你也可以if == "0001/1/1 0:00:00",我觉得可以理解成复杂的值类型使用比较频繁,简单的值类型像int直接if == 0就完事儿了。

简单示例

public class NullableTypeExample  
{  
    int normalInt = 10;           // 值类型  
    int? nullableInt = 10;        // 还是值类型,Nullable<int>  
    Nullable<int> sameAsAbove = 10;  // 与 int? 完全相同  

    public void Example()  
    {  
        // 检查类型  
        Console.WriteLine(normalInt.GetType());      // System.Int32  
        Console.WriteLine(nullableInt.GetType());    // System.Int32  
        Console.WriteLine(typeof(Nullable<int>));    // System.Nullable`1[System.Int32]  
    }  
}  

内存分配

public class MemoryExample  
{  
    public void ShowMemoryAllocation()  
    {  
        int normal = 42;          // 4字节  
        int? nullable = 42;       // 8字节(4字节值 + 1字节标志位,对齐到8字节)  
        
        // 结构体示例  
        struct MyStruct  
        {  
            public int Value;     // 4字节  
        }  
        
        MyStruct ms = new MyStruct();        // 4字节  
        MyStruct? nullableStruct = ms;       // 8字节  
    }  
}  

 性能比较

public class PerformanceExample  
{  
    public void ComparePerformance()  
    {  
        // 值类型操作 - 直接在栈上操作  
        int a = 1;  
        int b = a;  // 简单复制值  
        
        // 可空值类型操作 - 仍在栈上,但有额外开销  
        int? x = 1;  
        int? y = x;  // 复制值和标志位  
        
        // 引用类型操作 - 在堆上分配  
        string str1 = "test";  
        string str2 = str1;  // 复制引用  
    }  
}  

 装箱和拆箱

public class BoxingExample  
{  
    public void ShowBoxing()  
    {  
        // 普通值类型的装箱  
        int normal = 42;  
        object boxed1 = normal;        // 装箱  
        
        // 可空值类型的装箱  
        int? nullable = 42;  
        object boxed2 = nullable;      // 有值时才装箱  
        
        // null不会导致装箱  
        int? nullValue = null;  
        object boxed3 = nullValue;     // 不会装箱,直接是null  
    }  
}  

方法调用对比 

public class MethodCallExample  
{  
    // 值类型参数  
    public void ProcessValue(int value)  
    {  
        // 直接使用值  
    }  
    
    // 可空值类型参数  
    public void ProcessNullable(int? value)  
    {  
        if (value.HasValue)  
        {  
            int actualValue = value.Value;  
            // 使用实际值  
        }  
    }  
    
    // 引用类型参数  
    public void ProcessReference(string value)  
    {  
        if (value != null)  
        {  
            // 使用引用  
        }  
    }  
}  

结构体示例 

public struct Point  
{  
    public int X { get; set; }  
    public int Y { get; set; }  
}  

public class StructExample  
{  
    public void Example()  
    {  
        // 普通结构体  
        Point p1 = new Point { X = 1, Y = 2 };  
        
        // 可空结构体  
        Point? p2 = new Point { X = 1, Y = 2 };  
        Point? p3 = null;  // 可以赋值null  
        
        // 访问成员  
        if (p2.HasValue)  
        {  
            int x = p2.Value.X;  // 必须先检查HasValue  
        }  
        
        // 使用空条件操作符  
        int? y = p2?.Y;  // 如果p2为null,y为null  
    }  
}  

?.

 空条件操作符

public class Person  
{  
    public string Name { get; set; }  
    public Address Address { get; set; }  
}  

public class Address  
{  
    public string City { get; set; }  
}  

public class NullConditionalExample  
{  
    public void Example()  
    {  
        Person person = null;  
        
        // 传统方式  
        string city = null;  
        if (person != null && person.Address != null)  
        {  
            city = person.Address.City;  
        }  
        
        // 使用空条件操作符  
        string city2 = person?.Address?.City;  // 如果person或Address为null,返回null  
        
        // 链式调用  
        int? length = person?.Name?.Length;  // 安全地获取字符串长度  
    }  
}  

??

空合并操作符

public class NullCoalescingExample  
{  
    public void Example()  
    {  
        string name = null;  
        
        // 传统方式  
        string displayName = name != null ? name : "Default";  
        
        // 使用空合并操作符  
        string displayName2 = name ?? "Default";  // 如果name为null,使用"Default"  
        
        // 链式使用  
        string result = null ?? "First" ?? "Second";  // 结果为"First"  
        
        // 与空条件操作符组合使用  
        Person person = null;  
        string city = person?.Address?.City ?? "Unknown City";  
    }  
}  

??=

空合并赋值操作符

空合并赋值操作符需要C#语言版本8.0及以上才支持

public class NullCoalescingAssignmentExample  
{  
    private string _name;  
    
    public void Example()  
    {  
        // 传统方式  
        if (_name == null)  
        {  
            _name = "Default";  
        }  
        
        // 使用空合并赋值操作符  
        _name ??= "Default";  // 如果_name为null,则赋值为"Default"  
        
        // 示例2
        List<string> list = null;  
        (list ??= new List<string>()).Add("item");  // 如果list为null,创建新列表  
    }  
}  

相关文章:

  • 如何深刻理解Reactor和Proactor
  • MySQL学习笔记四
  • 城电科技 | 太阳能花怎么选择?光伏太阳花的应用场景在哪里?
  • 用 HTML、CSS 和 jQuery 打造多页输入框验证功能
  • ES:geoip_databases
  • AWS SNS深度解析:构建高可用、可扩展的云原生消息通信解决方案
  • 基于Java的人脸识别在线考试系统(jsp+springboot+mysql8.x)
  • 在PPT中同时自动播放多个视频的方法
  • AI智慧共治新未来——社会综合治理智慧化系统
  • 关于Spring MVC中传递数组参数的详细说明,包括如何通过逗号分隔的字符串自动转换为数组,以及具体的代码示例和总结表格
  • 十四届蓝桥杯Java省赛 B组(持续更新..)
  • 使用 Vue 快速集成 FullCalendar 日历组件教程
  • SpringBoot整合sa-token,Redis:解决重启项目丢失登录态问题
  • 滑动窗口-最小覆盖字串
  • UI测试(2)
  • 【Spring】小白速通AOP-日志记录Demo
  • 通信协议详解(九):SENT协议 —— 汽车传感器的“摩斯电码大师”
  • 01.win10/win11安装jdk,保姆级详解拆分步骤及命令的意义和报错解决方案
  • 基于Pyhon的京东笔记本电脑数据可视化分析系统
  • 非常适合做后台项目的go脚手架
  • 深圳网站建设培训/拼多多商品关键词搜索排名
  • 微信优惠群怎么做网站/seo文章生成器
  • 望城做网站找谁/上海app网络推广公司电话
  • 西安市建设局网站/广州aso优化公司 有限公司
  • 阳江招聘网官网/广州seo关键词
  • 大型网站 中小型网站/g3云推广靠谱吗