C#复习笔记(3)--C#2:解决C#1的问题(可空值类型)

可空值类型

C#2推出可空类型来表示可以为null的值类型。这是一个呼声很高的需求,因为在常用的数据库中都是允许某些值类型可为空的。那么为什么值类型就不能为空呢?内存中用一个全0的值来表示null,但是全0的地址说明了这个内存空间是被清除了的。所以对象选择用这种方式来初始化。用byte类型来举个例子:byte类型用8位来表示一个值,也就是说byte类型可以表示的数据最多是256个(2的8次方)。这256个值中的每一个值都是有用的,我们不可能吧其中一个值永远的舍弃掉从而来表示一个null值。对于引用类型,引用类型的变量的值在内存中在特定的操作系统中是固定的,32位是4字节,64位是8字节,32位的地址能最多表示42亿个对象,就是说这个能表示的地址太多了,所以,可以将一个全0的地址单独拿出来作为null值来用,因为地址多得永远都用不完。

先来看一下C#1中还没有可空值类型的时候是如何解决这些需求的。

方法1:使用一个魔值。确切的来说,是使用一个特定值来表示一个空值,比如DateTime.MinValue,但是这个办法很牵强,没有很好的说服力,它只是一个实现可控值类型的权宜之计。

方法2:引用类型的包装,值类型的优点之一是不需要GC去回收,把一个值类型包装成一个引用类型,GC的开销问题没有很好的解决。同时,值类型同引用类型的转换会造成装箱和拆箱,虽然C#2的泛型能够解决这个问题,但是开头说的垃圾回收没有解决。

方法3:用一个全新的值类型来表示可空值类型,这个值类型中包含一个bool值来表示是否包含一个真正的值,并包含一个表示这个值的属性。方法3正是C#2中做出的最终的决定:Nullable<T>,可空值类型。

一、定义

可空类型的核心部分是System. Nullable< T>。 除此之外,静态 类 System. Nullable 提供了一些工具方法, 可以简化可空类型的使用。

先来看一下定义:

 //// 摘要://     Represents a value type that can be assigned null.//// 类型参数://   T://     The underlying value type of the System.Nullable`1 generic type.public struct Nullable<T> where T : struct{//// 摘要://     Initializes a new instance of the System.Nullable`1 structure to the specified//     value.//// 参数://   value://     A value type.public Nullable(T value);//// 摘要://     Gets a value indicating whether the current System.Nullable`1 object has a valid//     value of its underlying type.//// 返回结果://     true if the current System.Nullable`1 object has a value; false if the current//     System.Nullable`1 object has no value.public bool HasValue { get; }//// 摘要://     Gets the value of the current System.Nullable`1 object if it has been assigned//     a valid underlying value.//// 返回结果://     The value of the current System.Nullable`1 object if the System.Nullable`1.HasValue//     property is true. An exception is thrown if the System.Nullable`1.HasValue property//     is false.//// 异常://   T:System.InvalidOperationException://     The System.Nullable`1.HasValue property is false.public T Value { get; }//public override bool Equals(object other);//// 摘要://     Retrieves the hash code of the object returned by the System.Nullable`1.Value//     property.//// 返回结果://     The hash code of the object returned by the System.Nullable`1.Value property//     if the System.Nullable`1.HasValue property is true, or zero if the System.Nullable`1.HasValue//     property is false.public override int GetHashCode(); // // 摘要: // Retrieves the value of the current System.Nullable`1 object, or the object's // default value. // // 返回结果: // The value of the System.Nullable`1.Value property if the System.Nullable`1.HasValue // property is true; otherwise, the default value of the current System.Nullable`1 // object. The type of the default value is the type argument of the current System.Nullable`1 // object, and the value of the default value consists solely of binary zeroes. public T GetValueOrDefault(); // // 摘要: // Retrieves the value of the current System.Nullable`1 object, or the specified // default value. // // 参数: // defaultValue: // A value to return if the System.Nullable`1.HasValue property is false. // // 返回结果: // The value of the System.Nullable`1.Value property if the System.Nullable`1.HasValue // property is true; otherwise, the defaultValue parameter. public T GetValueOrDefault(T defaultValue); // // 摘要: // Returns the text representation of the value of the current System.Nullable`1 // object. // // 返回结果: // The text representation of the value of the current System.Nullable`1 object // if the System.Nullable`1.HasValue property is true, or an empty string ("") if // the System.Nullable`1.HasValue property is false. public override string ToString(); public static implicit operator T? (T value); public static explicit operator T(T? value); }
  • 包含一个接受一个参数的构造函数,这个构造函数传入一个非可空值进行初始化,例如:Nullable<int> a=new Nullable<int>(5);
  • 包含一个HasValue属性来指示是否包含一个真正的值。
  • 如果HasValue返回true,可以使用Value属性来返回这个值。如果没有判断HasValue直接使用Value,可能会得到一个System.InvalidOperationException的异常。
  • Nullable是不易变的,一般来说,值类型都是不易变的,也就是说已经创建就不会再改变。值类型的复制方式就是复制一个副本,这个副本会在内存形成一个新的地址。
  • GetValueOrDefault()可以返回一个值(如果有)或者返回一个null(如果没有),它有重载的方法,向内部传入一个字面量会在没有真正的值存在的情况下拿这个传入的字面量当作一个默认值。
  • 其他的方法都是重写了object里面的。

最后, 框架提供了两个转换。 首先, 是T到Nullable< T> 的隐式转换。 转换结果为一个HasValue属性为true的实例。 同样,Nullable<T> 可以显式转换为T, 其作用与Value属性相同, 在没有真正的值可供返回时将抛出一个异常。

包装( wrapping) 和 拆 包( unwrapping)--- 将T的实例转换成Nullable<T> 的实例的过程在C#语言规范中称为包装, 相反的过程则称为拆包。 在C#语言规范中, 分别是在涉及“ 接受一个参数的构造函数” 和 Value 属性时定义的这两个术语。

二、Nullable<T>的装箱和拆箱

它是值类型,所以会涉及到装箱和拆箱。

装箱:Nullable<T>的实例要么装箱成空引用(如果没有值),要么装箱成T的一个已装箱值。不存在“装箱的可空int”。

 Nullable<int> nullable = 5;object boxed = nullable;Console.WriteLine(boxed.GetType());//这里会输出System.Int32,印证了不存在“装箱的可空int”。

 

拆箱:已装箱的值要么拆箱成一个普通类型,要不拆箱成对应的可空类型。拆箱一个空引用时,如果拆箱成普通类型,会抛出System.NullReferenceException:

 Nullable<int> a = new Nullable<int>();object b = a;int c = (int) b;//System.NullReferenceException

但如果拆箱成恰当的可空值类型,则会产生一个没有值的实例。下面的则不会抛出错误:

 Nullable<int> a = new Nullable<int>();object b = a;var c = (Nullable<int>) b;

三、Nullable<T>实例的相等性

Nullable< T> 覆盖了object.Equals( object),注意这个方法需要传入一个object的类型的实例,所以,传入的Nullable会进行装箱。Nullable装箱的原理上面有描述。这个方法基本与我们期望的一致,没有什么大的问题。

四、来自非泛型Nullable类的支持

Nullable有两个方法:

        public static int Compare<T>(T? n1, T? n2) where T : struct;public static bool Equals<T>(T? n1, T? n2) where T : struct;

Compare是用Compare<T>.Default来比较两个的大小:

 Nullable<int> a = 5;Nullable<int> b = 5;          var defaults = Comparer<int?>.Default;Console.WriteLine(defaults.Compare(a,b));//0

Equals使用EqualityComparer< T>. Default。

对于没有值的实例, 上述每个方法返回的值都遵从.NET的约定:空值与空值相等, 小于其他所有值。

 

五、语法糖

?。使用这个修饰符放到int后面,int?的含义与Nullable<int>的含义完全一样,包括生成的IL。就像int和System.Int32换着用一样。

与null值的比较

可以将null赋给一个可空值类型的实例,表示一个没有真实值的可空值类型。

int? a = null;

可空值类型和其基础类型的一些匹配的行为

标题中提到的基础类型是这么一个概念:int?的基础类型就是int。

假如一个非可空的值类型支持一个操作符或者一种转换,而且那个操作符或者转换只涉及其他非可空的值类型时, 那么可空的值类型也支持相同的操作符或转换。 下面举一个更具体的例子。 我们知道,int到long存在着一个隐式转换, 这就意味着 int? 到 long? 也存在一个隐式转换, 其行为可想而知。

因为int和long存在这么一种隐式转换的规则,那么,就存在:

int?到long?的隐式转换

int到long?的隐式转换

int?到long的显示转换。

int a = 1;
long? b = a;//隐式转换
int? c = 1;
long? d = c;//隐式转换
int? e = 1;
long f =(long) e;//显示的转换

 

转换和操作符

将基础类型的一些转换行为应用到对应的可空类型上的转换行为叫做提升转换,将基础类型的一些操作符的行为应用到相应可空值类型的操作符叫做提升操作符。基础类型重载操作符后,对应的可空类型就可享用这个重载。

这里的只是还需要从书中进行补充,未完待续。。。。

空合并操作符

这个二元操作符在对 first ?? second 求值 时, 大致会经历以下步骤:

1、对first进行求值

2、如果结果非空,表达式的值和类型就已经确定

3、如果结果为空,继续计算second的值并将结果的值作为整个表达式的值。

 int? a = null;int c = a ?? 1;

很明显这里涉及到了类型转换的问题,我们可以直接将int类型的c变量赋给这个表达式,因为second是非可空的。

转载于:https://www.cnblogs.com/pangjianxin/p/8652016.html

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

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

相关文章

ISA之三种客户端访问

我们已经懂得怎么搭建ISA2006.我们今天来利用ISA访问外网&#xff01;顺便说声如果你IP&#xff0c;网关&#xff0c;DNS什么都没问题。那么你可以看看你的NAT处理&#xff01;下面我们看看我们的试验拓扑&#xff01;我们在ISA的服务器上做访问规则&#xff01;来允许我们可以…

面试官不讲武德,居然让我讲讲蠕虫和金丝雀!

1. 蠕虫病毒简介2. 缓冲区溢出3. 缓冲区溢出举例4. 缓冲区溢出的危害5. 内存在计算机中的排布方式6. 计算机中越界访问的后果7. 避免缓冲区溢出的三种方法7.1 栈随机化7.2 检测栈是否被破坏7.3 限制可执行代码区域8. 总结蠕虫病毒是一种常见的利用Unix系统中的缺点来进行攻击的…

asp.net core 拦击器制作的权限管理系统DEMO

效果图 没有登陆不会执行请求日期的方法&#xff0c;不管是否登陆都不允许访问请求时间方法 验证不通过是会进行转发到Home/error方法中&#xff0c; 代码附上&#xff1a; [Route("[controller]/[action]")]public class HomeController : BaseController{/// <s…

工程师姓什么很重要!别再叫我“X工”!!!

工程师之间都是这么互相打招呼的——“高工&#xff0c;你设计图通过了么&#xff1f;”“李工&#xff0c;工程画完了吗&#xff1f;”“王工&#xff0c;你真是越来越漂亮了&#xff01;”"张工&#xff0c;你的DFM整完了吗"“周公&#xff0c;Schedule 该更新了”…

说一下NFC,手机有NFC功能却不能模拟门禁卡?

img1、NFC是什么&#xff1f;NFC&#xff08;Near Field Communication&#xff09; 技术由Philips、Nokia和Sony主推的一种近距离无线通信技术&#xff08;NFCIP-1&#xff09;&#xff0c;是一种短距离非接触式的通信方式&#xff0c;通常有效通讯距离为4厘米以内。工作频率为…

小程序员的大梦想 与盖茨像哥们儿

小程序员的大梦想 与盖茨像哥们儿以10亿的天价转会新华都&#xff0c;让唐骏有机会开创其职业经理人生涯的新局面&#xff0c;但在此之前&#xff0c;他的成功已得到证明面前的唐骏温和得令人吃惊。仿佛“前微软中国区总裁”、“打工皇帝”、“10亿转会身价”这样的光环带给他的…

动态规划详解

个人见解&#xff1a;1.动态规划实现了把问题拆分成多个子问题&#xff0c;然后求解&#xff0c;子问题有解后&#xff0c;问题自然迎刃而解&#xff1b;2.动态规划实现了子问题的状态的迁移&#xff0c;保存每个状态值&#xff0c;递推出答案&#xff0c;但不记录每种状态的求…

我的奶奶

突然想起我奶奶&#xff0c;是突然发现&#xff0c;距离奶奶去世已经有快十年&#xff0c;这十年时间&#xff0c;我也再也没有见过奶奶。奶奶刚去世的前几年&#xff0c;有时候会梦到奶奶跟我说话&#xff0c;她总是会很耐心的告诉我很多道理。奶奶从小到大都没有指责过我&…

WPF应用程序内存泄漏的一些原因

原文&#xff1a;Finding Memory Leaks in WPF-based applications There are numbers of blogs that folks wrote about memory leaks in Microsoft .Net Framework managed code and unmanaged code based applications. In this blog I wanted to: Show coding practices th…

[转]Eclipse RCP应用系统开发方法与实战2-- 定制应用程序窗口属性

5.1.4 定制应用程序窗口属性 向导生成的应用程序主界面并不能满足要求&#xff0c;存在很多问题&#xff0c;例如&#xff0c;主界面运行时没有自动居中&#xff0c;主界面大小没有固 定&#xff0c;主窗口标题栏文字应该是“高校经费测算系统”。再看看图5-3、图5-4的标题栏有…

赢在中国 - 史玉柱经典语录

1.要重视建立销售手册2.凡是先做试点&#xff0c;风险才低。3.找到自己的细分市场。4.不要总想着同竞争对手对立&#xff0c;而是要想办法让自己弥补竞争对手的不足。5. 如果没有价格上的优势与技术上的绝对优势&#xff0c;千万不要进入红海市场&#xff0c;否则你会必输无疑&…

我最近在学微信小程序开发,一起吗?

从当初的一夜成名&#xff0c;到今天火爆的市场占有率&#xff0c;微信小程序已走过 4 个年头。据今年 1 月阿拉丁发布的报告显示&#xff0c;微信小程序 2020 年 DAU 已破 4 亿&#xff0c;其总数超 380 万。最近有读者问我说&#xff0c;发哥&#xff0c;之前自己一直是个人…

WebService大讲堂之Axis2(2):复合类型数据的传递

在实际的应用中&#xff0c;不仅需要使用WebService来传递简单类型的数据&#xff0c;有时也需要传递更复杂的数据&#xff0c;这些数据可以被称为复合类型的数据。数组与类&#xff08;接口&#xff09;是比较常用的复合类型。在Axis2中可以直接使用将WebService方法的参数或返…

Linux虚拟摄像头vivid配置

总述最近在看摄像头驱动&#xff0c;需要配置虚拟摄像头的驱动&#xff0c;但是教程里面是linux2.6内核的&#xff0c;实际电脑的是Ubuntu16&#xff0c;内核是linux4.15版本&#xff0c;从2.6到4.15内核好多文件发生了变化&#xff0c;所以我们该怎么操作呢&#xff1f;下面就…

第一次工作报告

要求 1. 对源文件&#xff08;*.txt,*.cpp,*.h,*.cs,*.html,*.js,*.java,*.py,*.php等&#xff09;统计字符数、单词数、行数、词频&#xff0c;统计结果以指定格式输出到默认文件中&#xff0c;以及其他扩展功能&#xff0c;并能够快速地处理多个文件。 2. 使用性能…

树莓派Pico的一些有趣的基本实验

▲ 实验电路板Raspberry PI Pico小型MCU模块&#xff0c;以其价格低廉&#xff0c;功能丰富&#xff0c;开发方便为很多非电子类专业的同学进行创意项目原型设计提供了方便的平台。下面的一些实验给CDIE课程设计同学们制作的一些基本演示实验。▌01 PI Pico实验板在 RASPBERRY …

Gabor变换

gabor变换分析非平稳信号有弊端主要是时频窗宽度固定 小波wavelet a小窗窄a大窗宽 窗口或短时傅氏变换在时域上和频域上的局部化程度主要由窗函数g(x)的有效时宽Δt 和有效带宽Δf 决定。Δt 和Δf 越小, 表明局部性越好。但Heisenberg 测不准原理指出[ 6] :Δt 和Δf 不可能任…

30块钱的树莓派跑unix系统,源码全部开源,香

▌ 1、前言之前做活动抽奖送的几个树莓派&#xff0c;但是因为好几个人都没有填写地址&#xff0c;所以就只能把东西寄回来给我&#xff0c;然后手痒自己玩了下&#xff0c;觉得这个东西确实很香&#xff0c;比一般的Linux开发板都好。PICO这个开发板可以玩很多东西1 、运行pic…

为什么大家都只谈薪资,却不谈梦想?

说个薪资的问题&#xff0c;最近在帮一个朋友物色工作&#xff0c;当然&#xff0c;除了我那个朋友以外&#xff0c;也有挺多同学向我咨询offer薪资的问题。先说我那个朋友。高中毕业后去当兵&#xff0c;服兵役结束后去4s店修车&#xff0c;我车子的很多问题也会向他咨询&…

差生的 8 年程序员总结

今年终于从大菊花厂离职了&#xff0c;离职前收入大概60w不到吧&#xff0c;在某乎属于比较差的&#xff0c;今天终于有空写一下自己的职场故事&#xff0c;也算是给自己近8年的程序员工作做个总结复盘。近8年有些事情做对了&#xff0c;也有更多事情做错了&#xff0c;在这里记…