C#学习笔记(六):可空类型、匿名方法和迭代器

可空类型

为啥要引入可空类型?

在数据库中,字段是可以为null值的,那么在C#中为了方便的操作数据库的值,微软引入了可空类型。

声明可空类型

我们可以使用两种方法声明一个可空类型:

1 Nullable<int> i = null;
2 int? i = null;

第二行是第一行的简写方法,其中“?”是微软为可空类型提供的一个语法糖。

我们看看可空类型的实现:

  1 // Type: System.Nullable`1
  2 // Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
  3 // MVID: 255ABCDF-D9D6-4E3D-BAD4-F74D4CE3D7A8
  4 // Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll
  5
  6 using System.Runtime;
  7
  8 namespace System
  9 {
 10   /// <summary>
 11   /// 表示基础类型为值类型的对象,值类型与引用类型一样也可以分配 null。
 12   /// </summary>
 13   /// <typeparam name="T"><see cref="T:System.Nullable`1"/> 泛型类型的基础值类型。</typeparam><filterpriority>1</filterpriority>
 14   [Serializable]
 15   public struct Nullable<T> where T : struct
 16   {
 17     /// <summary>
 18     /// 将 <see cref="T:System.Nullable`1"/> 结构的新实例初始化为指定值。
 19     /// </summary>
 20     /// <param name="value">一个值类型。</param>
 21     [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
 22     public Nullable(T value);
 23     /// <summary>
 24     /// 创建一个新的 <see cref="T:System.Nullable`1"/> 对象,并将其初始化为指定的值。
 25     /// </summary>
 26     ///
 27     /// <returns>
 28     /// 一个 <see cref="T:System.Nullable`1"/> 对象,其 <see cref="P:System.Nullable`1.Value"/> 属性使用 <paramref name="value"/> 参数进行初始化。
 29     /// </returns>
 30     /// <param name="value">一个值类型。</param>
 31     public static implicit operator T?(T value);
 32     /// <summary>
 33     /// 返回指定的 <see cref="T:System.Nullable`1"/> 的值。
 34     /// </summary>
 35     ///
 36     /// <returns>
 37     /// <paramref name="value"/> 参数的 <see cref="P:System.Nullable`1.Value"/> 属性的值。
 38     /// </returns>
 39     /// <param name="value">一个 <see cref="T:System.Nullable`1"/> 值。</param>
 40     public static explicit operator T(T? value);
 41     /// <summary>
 42     /// 检索当前 <see cref="T:System.Nullable`1"/> 对象的值,或该对象的默认值。
 43     /// </summary>
 44     ///
 45     /// <returns>
 46     /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,则为 <see cref="P:System.Nullable`1.Value"/> 属性的值;否则为当前 <see cref="T:System.Nullable`1"/> 对象的默认值。 默认值的类型为当前 <see cref="T:System.Nullable`1"/> 对象的类型参数,而默认值的值中只包含二进制零。
 47     /// </returns>
 48     [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
 49     public T GetValueOrDefault();
 50     /// <summary>
 51     /// 检索当前 <see cref="T:System.Nullable`1"/> 对象的值或指定的默认值。
 52     /// </summary>
 53     ///
 54     /// <returns>
 55     /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,则为 <see cref="P:System.Nullable`1.Value"/> 属性的值;否则为 <paramref name="defaultValue"/> 参数。
 56     /// </returns>
 57     /// <param name="defaultValue">如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 false,则为一个返回值。</param>
 58     public T GetValueOrDefault(T defaultValue);
 59     /// <summary>
 60     /// 指示当前 <see cref="T:System.Nullable`1"/> 对象是否等于指定的对象。
 61     /// </summary>
 62     ///
 63     /// <returns>
 64     /// 如果 <paramref name="other"/> 等于当前的 <see cref="T:System.Nullable`1"/> 对象,则为 true;否则为 false。 此表描述如何定义所比较值的相等性: 返回值 说明 true <see cref="P:System.Nullable`1.HasValue"/> 属性为 false,并且 <paramref name="other"/> 参数为 null。 即,根据定义,两个 null 值相等。 - 或 - <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,并且 <see cref="P:System.Nullable`1.Value"/> 属性返回的值等于 <paramref name="other"/> 参数。 false 当前 <see cref="T:System.Nullable`1"/> 结构的 <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,并且 <paramref name="other"/> 参数为 null。 - 或 - 当前 <see cref="T:System.Nullable`1"/> 结构的 <see cref="P:System.Nullable`1.HasValue"/> 属性为 false,并且 <paramref name="other"/> 参数不为 null。 - 或 - 当前 <see cref="T:System.Nullable`1"/> 结构的 <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,并且 <see cref="P:System.Nullable`1.Value"/> 属性返回的值不等于 <paramref name="other"/> 参数。
 65     /// </returns>
 66     /// <param name="other">一个对象。</param><filterpriority>1</filterpriority>
 67     public override bool Equals(object other);
 68     /// <summary>
 69     /// 检索由 <see cref="P:System.Nullable`1.Value"/> 属性返回的对象的哈希代码。
 70     /// </summary>
 71     ///
 72     /// <returns>
 73     /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,则为 <see cref="P:System.Nullable`1.Value"/> 属性返回的对象的哈希代码;如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 false,则为零。
 74     /// </returns>
 75     /// <filterpriority>1</filterpriority>
 76     public override int GetHashCode();
 77     /// <summary>
 78     /// 返回当前 <see cref="T:System.Nullable`1"/> 对象的值的文本表示形式。
 79     /// </summary>
 80     ///
 81     /// <returns>
 82     /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,则是当前 <see cref="T:System.Nullable`1"/> 对象的值的文本表示形式;如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 false,则是一个空字符串 ("")。
 83     /// </returns>
 84     /// <filterpriority>1</filterpriority>
 85     public override string ToString();
 86     /// <summary>
 87     /// 获取一个值,指示当前的 <see cref="T:System.Nullable`1"/> 对象是否有值。
 88     /// </summary>
 89     ///
 90     /// <returns>
 91     /// 如果当前的 <see cref="T:System.Nullable`1"/> 对象具有值,则为 true;如果当前的 <see cref="T:System.Nullable`1"/> 对象没有值,则为 false。
 92     /// </returns>
 93     public bool HasValue { [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; }
 94     /// <summary>
 95     /// 获取当前的 <see cref="T:System.Nullable`1"/> 值。
 96     /// </summary>
 97     ///
 98     /// <returns>
 99     /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 true,则为当前 <see cref="T:System.Nullable`1"/> 对象的值。 如果 <see cref="P:System.Nullable`1.HasValue"/> 属性为 false,则将引发异常。
100     /// </returns>
101     /// <exception cref="T:System.InvalidOperationException"><see cref="P:System.Nullable`1.HasValue"/> 属性为 false。</exception>
102     public T Value { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get; }
103   }
104 }

我们注意一下其类的声明:

public struct Nullable<T> where T : struct

首先,可空类型是值类型而不是引用类型。

where表明了其接受的类型仅仅是值类型,当然,引用类型天生就支持为null。

使用可空类型

我们来看一个使用可空的例子:

 1 using System;
 2
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             int? i = null;
10
11             // GetValueOrDefault() 如果为空则返回默认值
12             Console.WriteLine("是否有值:" + i.HasValue + ", 值:" + i.GetValueOrDefault());
13
14             //赋值
15             if (!i.HasValue)
16             {
17                 i = 100;
18             }
19
20             Console.WriteLine("是否有值:" + i.HasValue + ", 值:" + i.Value);
21
22             //int num = i * 2;
23             //上面的写法会报错
24             int num = i.Value * 2;
25             Console.WriteLine("num:" + num);
26
27             if (i == 100)
28             {
29                 Console.WriteLine("等于100");
30             }
31
32             Console.Read();
33         }
34     }
35 }

输出如下:

1 是否有值:False, 值:0
2 是否有值:True, 值:100
3 num:200
4 等于100

空合并操作符

由于可空类型可以为空,所以,如果我们需要获取一个可空类型的值时,如果为null返回0,否则返回其自己的值,写法如下:

int i = nullable.HasValue ? nullable.Value : 0;

我们还可以直接使用GetValueOrDefault();方法来获取,如果是为null需要一个指定的数,如100的写法如下:

1 int i = nullable.HasValue ? nullable.Value : 100;
2 int i = nullable.GetValueOrDefault(100);

上面两种写法的效果一致。

下面我们来看看空合并操作符“??”的效果:判断左方的数,如果不为空则返回左方的数,否则返回右方的数。

比如上面的效果用空合并操作符来写如下:

int i = nullable ?? 100;

我们可以把空操作符看做一种方便的简写形式。

匿名方法

委托、匿名函数、Lambda表达式和事件的学习

迭代器

IEnumerable、IEnumerator与yield的学习

yield学习续:yield return迭代块在Unity3D中的应用——协程

时间: 2024-10-01 03:54:41

C#学习笔记(六):可空类型、匿名方法和迭代器的相关文章

C#学习笔记三: C#2.0泛型 可控类型 匿名方法和迭代器

前言 C#1.0的委托特性使方法作为其他方法的参数来传递,而C#2.0 中提出的泛型特性则使类型可以被参数化,从而不必再为不同的类型提供特殊版本的实现方法.另外C#2.0还提出了可空类型,匿名方法和迭代器3个优美的特性. 1,泛型1.1 泛型是什么泛型的英文表述是"generic", 这个单词意为通用的.从字面意思可知,泛型代表的就是"通用类型",它可以代替任意的数据类型,使类型参数化,从而达到之实现一个方法就可以操作多种数据类型的目的.泛型是将方法实现行为与方法操

ActiveMQ学习笔记(六)——JMS消息类型

1.前言 ActiveMQ学习笔记(四)--通过ActiveMQ收发消息http://my.oschina.net/xiaoxishan/blog/380446 和ActiveMQ学习笔记(五)--使用Spring JMS收发消息http://my.oschina.net/xiaoxishan/blog/381209   中,发送和接受的消息类型都是TextMessage,即文本消息(如下面的代码所示).显然消息类型只有文本类型是不能满足要求的. //发送文本消息  session.create

初探swift语言的学习笔记六(ARC-自动引用计数,内存管理)

Swift使用自动引用计数(ARC)来管理应用程序的内存使用.这表示内存管理已经是Swift的一部分,在大多数情况下,你并不需要考虑内存的管理.当实例并不再被需要时,ARC会自动释放这些实例所使用的内存. 另外需要注意的: 引用计数仅仅作用于类实例上.结构和枚举是值类型,而非引用类型,所以不能被引用存储和传递. swift的ARC工作过程 每当创建一个类的实例,ARC分配一个内存块来存储这个实例的信息,包含了类型信息和实例的属性值信息. 另外当实例不再被使用时,ARC会释放实例所占用的内存,这些

Lua学习笔记(六):函数-续

Lua中的函数是带有词法定界(lexical scoping)的第一类值(first-class values).第一类值指:在Lua中函数和其他值(数值.字符串)一样,函数可以被存放在变量中,也可以存放在表中,可以作为函数的参数,还可以作为函数的返回值.词法定界指:嵌套的函数可以访问他外部函数中的变量.这一特性给Lua提供了强大的编程能力. Lua中关于函数稍微难以理解的是函数也可以没有名字,匿名的.当我们提到函数名(比如print),实际上是说一个指向函数的变量,像持有其他类型的变量一样:

swift学习笔记(六)析构过程和使用闭包对属性进行默认值赋值

一.通过闭包和函数实现属性的默认值 当某个存储属性的默认值需要定制时,可以通过闭包或全局函数来为其提供定制的默认值. 注:全局函数结构体和枚举使用关键字static标注    函数则使用class关键字标注 当对一个属性使用闭包函数进行赋值时,每当此属性所述的类型被创建实例时,对应的闭包或函数会被调用,而他们的返回值会被作为属性的默认值. ESC: Class SomeCLass{ let someProperty:SomeType={ //给someProperty赋一个默认值 //返回一个与

java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessController的checkPerssiom方法,访问控制器AccessController的栈检查机制又遍历整个 PerssiomCollection来判断具体拥有什么权限一旦发现栈中一个权限不允许的时候抛出异常否则简单的返回,这个过程实际上比我的描述要复杂 得多,这里我只是简单的一句带过,因为这

python之raw_input()(学习笔记六)

python之raw_input()(学习笔记六) 我们经常使用raw_input()读取用户的输入,如下例子所示: >>> name = raw_input('please input your name:'),截图如下: 下面简单说下,raw_input()与if搭配使用,脚本如下: #!/usr/bin/env python # -*- coding:utf-8 -*- birth = raw_input('birth:') if birth < 2000: print '0

python学习笔记2—python文件类型、变量、数值、字符串、元组、列表、字典

python学习笔记2--python文件类型.变量.数值.字符串.元组.列表.字典 一.Python文件类型 1.源代码 python源代码文件以.py为扩展名,由pyton程序解释,不需要编译 [[email protected] day01]# vim 1.py #!/usr/bin/python        print 'hello world!' [[email protected] day01]# python 1.py hello world! 2.字节代码 Python源码文件

javascript学习笔记---ECMAScript-判断变量类型

判断类型之前,先要清楚有哪些类型. (理理思路:程序由数据和方法构成,数据由简单数据和复杂数据构成) 即类型有: 数据(简单数据:boolean,string,num,undefined,null.复杂数据:object), 方法(function) 万能的typeof,神一样的方法 typeof(1);// num typeof("hello");// string   typeof(false);// boolean var vFlag; typeof(vFlag);// unde

Linux 程序设计学习笔记----Linux下文件类型和属性管理

转载请注明出处:http://blog.csdn.net/suool/article/details/38318225 部分内容整理自网络,在此感谢各位大神. Linux文件类型和权限 数据表示 文件属性存储结构体Inode的成员变量i_mode存储着该文件的文件类型和权限信息.该变量为short int类型. 这个16位变量的各个位功能划分为: 第0-8位为权限位,为别对应拥有者(user),同组其他用户(group)和其他用户(other)的读R写W和执行X权限. 第9-11位是权限修饰位,