C#学习笔记(六):可空类型、匿名方法和迭代器
可空類型
為啥要引入可空類型?
在數(shù)據(jù)庫中,字段是可以為null值的,那么在C#中為了方便的操作數(shù)據(jù)庫的值,微軟引入了可空類型。
聲明可空類型
我們可以使用兩種方法聲明一個(gè)可空類型:
1 Nullable<int> i = null; 2 int? i = null;第二行是第一行的簡(jiǎn)寫方法,其中“?”是微軟為可空類型提供的一個(gè)語法糖。
我們看看可空類型的實(shí)現(xiàn):
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 /// 表示基礎(chǔ)類型為值類型的對(duì)象,值類型與引用類型一樣也可以分配 null。 12 /// </summary> 13 /// <typeparam name="T"><see cref="T:System.Nullable`1"/> 泛型類型的基礎(chǔ)值類型。</typeparam><filterpriority>1</filterpriority> 14 [Serializable] 15 public struct Nullable<T> where T : struct 16 { 17 /// <summary> 18 /// 將 <see cref="T:System.Nullable`1"/> 結(jié)構(gòu)的新實(shí)例初始化為指定值。 19 /// </summary> 20 /// <param name="value">一個(gè)值類型。</param> 21 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 22 public Nullable(T value); 23 /// <summary> 24 /// 創(chuàng)建一個(gè)新的 <see cref="T:System.Nullable`1"/> 對(duì)象,并將其初始化為指定的值。 25 /// </summary> 26 /// 27 /// <returns> 28 /// 一個(gè) <see cref="T:System.Nullable`1"/> 對(duì)象,其 <see cref="P:System.Nullable`1.Value"/> 屬性使用 <paramref name="value"/> 參數(shù)進(jìn)行初始化。 29 /// </returns> 30 /// <param name="value">一個(gè)值類型。</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"/> 參數(shù)的 <see cref="P:System.Nullable`1.Value"/> 屬性的值。 38 /// </returns> 39 /// <param name="value">一個(gè) <see cref="T:System.Nullable`1"/> 值。</param> 40 public static explicit operator T(T? value); 41 /// <summary> 42 /// 檢索當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象的值,或該對(duì)象的默認(rèn)值。 43 /// </summary> 44 /// 45 /// <returns> 46 /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,則為 <see cref="P:System.Nullable`1.Value"/> 屬性的值;否則為當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象的默認(rèn)值。 默認(rèn)值的類型為當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象的類型參數(shù),而默認(rèn)值的值中只包含二進(jìn)制零。 47 /// </returns> 48 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 49 public T GetValueOrDefault(); 50 /// <summary> 51 /// 檢索當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象的值或指定的默認(rèn)值。 52 /// </summary> 53 /// 54 /// <returns> 55 /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,則為 <see cref="P:System.Nullable`1.Value"/> 屬性的值;否則為 <paramref name="defaultValue"/> 參數(shù)。 56 /// </returns> 57 /// <param name="defaultValue">如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 false,則為一個(gè)返回值。</param> 58 public T GetValueOrDefault(T defaultValue); 59 /// <summary> 60 /// 指示當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象是否等于指定的對(duì)象。 61 /// </summary> 62 /// 63 /// <returns> 64 /// 如果 <paramref name="other"/> 等于當(dāng)前的 <see cref="T:System.Nullable`1"/> 對(duì)象,則為 true;否則為 false。 此表描述如何定義所比較值的相等性: 返回值 說明 true <see cref="P:System.Nullable`1.HasValue"/> 屬性為 false,并且 <paramref name="other"/> 參數(shù)為 null。 即,根據(jù)定義,兩個(gè) null 值相等。 - 或 - <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,并且 <see cref="P:System.Nullable`1.Value"/> 屬性返回的值等于 <paramref name="other"/> 參數(shù)。 false 當(dāng)前 <see cref="T:System.Nullable`1"/> 結(jié)構(gòu)的 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,并且 <paramref name="other"/> 參數(shù)為 null。 - 或 - 當(dāng)前 <see cref="T:System.Nullable`1"/> 結(jié)構(gòu)的 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 false,并且 <paramref name="other"/> 參數(shù)不為 null。 - 或 - 當(dāng)前 <see cref="T:System.Nullable`1"/> 結(jié)構(gòu)的 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,并且 <see cref="P:System.Nullable`1.Value"/> 屬性返回的值不等于 <paramref name="other"/> 參數(shù)。 65 /// </returns> 66 /// <param name="other">一個(gè)對(duì)象。</param><filterpriority>1</filterpriority> 67 public override bool Equals(object other); 68 /// <summary> 69 /// 檢索由 <see cref="P:System.Nullable`1.Value"/> 屬性返回的對(duì)象的哈希代碼。 70 /// </summary> 71 /// 72 /// <returns> 73 /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,則為 <see cref="P:System.Nullable`1.Value"/> 屬性返回的對(duì)象的哈希代碼;如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 false,則為零。 74 /// </returns> 75 /// <filterpriority>1</filterpriority> 76 public override int GetHashCode(); 77 /// <summary> 78 /// 返回當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象的值的文本表示形式。 79 /// </summary> 80 /// 81 /// <returns> 82 /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,則是當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象的值的文本表示形式;如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 false,則是一個(gè)空字符串 ("")。 83 /// </returns> 84 /// <filterpriority>1</filterpriority> 85 public override string ToString(); 86 /// <summary> 87 /// 獲取一個(gè)值,指示當(dāng)前的 <see cref="T:System.Nullable`1"/> 對(duì)象是否有值。 88 /// </summary> 89 /// 90 /// <returns> 91 /// 如果當(dāng)前的 <see cref="T:System.Nullable`1"/> 對(duì)象具有值,則為 true;如果當(dāng)前的 <see cref="T:System.Nullable`1"/> 對(duì)象沒有值,則為 false。 92 /// </returns> 93 public bool HasValue { [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; } 94 /// <summary> 95 /// 獲取當(dāng)前的 <see cref="T:System.Nullable`1"/> 值。 96 /// </summary> 97 /// 98 /// <returns> 99 /// 如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 true,則為當(dāng)前 <see cref="T:System.Nullable`1"/> 對(duì)象的值。 如果 <see cref="P:System.Nullable`1.HasValue"/> 屬性為 false,則將引發(fā)異常。 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 } View Code我們注意一下其類的聲明:
public struct Nullable<T> where T : struct首先,可空類型是值類型而不是引用類型。
where表明了其接受的類型僅僅是值類型,當(dāng)然,引用類型天生就支持為null。
使用可空類型
我們來看一個(gè)使用可空的例子:
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() 如果為空則返回默認(rèn)值 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 //上面的寫法會(huì)報(bào)錯(cuò) 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空合并操作符
由于可空類型可以為空,所以,如果我們需要獲取一個(gè)可空類型的值時(shí),如果為null返回0,否則返回其自己的值,寫法如下:
int i = nullable.HasValue ? nullable.Value : 0;我們還可以直接使用GetValueOrDefault();方法來獲取,如果是為null需要一個(gè)指定的數(shù),如100的寫法如下:
1 int i = nullable.HasValue ? nullable.Value : 100; 2 int i = nullable.GetValueOrDefault(100);上面兩種寫法的效果一致。
下面我們來看看空合并操作符“??”的效果:判斷左方的數(shù),如果不為空則返回左方的數(shù),否則返回右方的數(shù)。
比如上面的效果用空合并操作符來寫如下:
int i = nullable ?? 100;我們可以把空操作符看做一種方便的簡(jiǎn)寫形式。
匿名方法
委托、匿名函數(shù)、Lambda表達(dá)式和事件的學(xué)習(xí)
閉包
一般一個(gè)方法內(nèi)部定義的值對(duì)象會(huì)在方法或其作用域結(jié)束時(shí)被系統(tǒng)回收,但是如果使用匿名函數(shù)和Lambda表達(dá)式時(shí)會(huì)引入一種新的情況,導(dǎo)致方法內(nèi)部定義的值對(duì)象不會(huì)再方法結(jié)束時(shí)被回收,這種想象稱為閉包。
閉包的概念:主要是指由函數(shù)以及與函數(shù)相關(guān)的上下文環(huán)境組成的實(shí)體,通過閉包,函數(shù)與上下文變量之間建立起關(guān)聯(lián)關(guān)系,上下文變量的狀態(tài)可以在函數(shù)的多次調(diào)用過程中持久保持,從作用域的角度而言,私有變量的生存期被延長(zhǎng),函數(shù)調(diào)用所生成的值在下次調(diào)用時(shí)仍被保持。從安全性的角度而言,閉包有利于信息隱蔽,私有變量只在該函數(shù)內(nèi)可見。
形成閉包的條件:嵌套定義的函數(shù)、匿名函數(shù)、將函數(shù)作為參數(shù)或者返回值。
我們來看一個(gè)閉包的例子:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 TCloser a = new TCloser(); 10 Func<int> b = a.T1(); 11 Console.WriteLine(b()); 12 13 Console.Read(); 14 } 15 } 16 17 public class TCloser 18 { 19 public Func<int> T1() 20 { 21 int n = 999; 22 return () => 23 { 24 Console.WriteLine(n); 25 return n; 26 }; 27 } 28 } 29 }我們會(huì)發(fā)現(xiàn),例子中T1的局部變量n,在T1執(zhí)行完畢后仍然被保留沒有被系統(tǒng)回收,而在其返回的方法中可以被使用到,這就是閉包。
迭代器?
IEnumerable、IEnumerator與yield的學(xué)習(xí)
yield學(xué)習(xí)續(xù):yield return迭代塊在Unity3D中的應(yīng)用——協(xié)程
總結(jié)
以上是生活随笔為你收集整理的C#学习笔记(六):可空类型、匿名方法和迭代器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 判断scrollview是否滚动到了底部
- 下一篇: gulp结构化实践