之前對於Break和Continue;ReadOnly和Const;ref和out,params之類的基礎東東學習過,但是一直沒有仔細去研究到底是怎麼一回事兒,最近在開發中用到了,仔細來做個總結:
1、Break和Continue
//break是跳出整個循環體,不再執行本循環,continue是結束單次循環,繼續下一次循環。 //更多問題 聯系QQ 931697811(夜雨梧桐)

1 #region Break測試
2
3 Console.WriteLine("========Break========");
4 int x = 0;
5 while (x++ < 20)
6 {
7 if (x == 3)
8 {
9 break;
10 }
11 Console.WriteLine("{0}\n",x);
12 }
13 #endregion
View Code

1 #region Continue測試
2 Console.WriteLine("========Continue========");
3 int k = 0;
4 while (k++ < 10)
5 {
6 if (k == 3)
7 {
8 continue;
9 }
10 Console.WriteLine("{0}\n",k);
11 }
12 #endregion
View Code

2、ReadOnly和Const
//有問題:聯系QQ 931697811
1. const修飾的常量在聲明的時候必須初始化;readonly修飾的常量則可以延遲到構造函數初始化
2. const修飾的常量在編譯期間就被解析,即常量值被替換成初始化的值;readonly修飾的常量則延遲到運行的時候
3. 此外const常量既可以聲明在類中也可以在函數體內,但是static readonly常量只能聲明在類中。

1 #region ReadOnly
2 static readonly int A = B * 10;
3 static readonly int B = 10;
4
5 const int j = k * 10;
6 const int k = 10;
7
8 static void Main(string[] args)
9 {
10 Console.WriteLine("===Readonly輸出的值是:===");
11 Console.WriteLine("A is {0}.B is {1}", A, B);
12 Console.WriteLine("===Const輸出的值是:===");
13 Console.WriteLine("j is {0}.k is {1}", j, k);
14 Console.ReadKey();
15 }
16 #endregion
View Code

3、ref和out,params
問題的引出:
現需要通過一個叫Swap的方法交換a,b兩個變量的值。交換前a=1,b=2,斷言:交換後a=2,b=1
現編碼如下:

1 1class Program
2 2 {
3 3 static void Main(string[] args)
4 4 {
5 5 int a = 1;
6 6 int b = 2;
7 7 Console.WriteLine("交換前\ta={0}\tb={1}\t",a,b);
8 8 Swap(a,b);
9 9 Console.WriteLine("交換後\ta={0}\tb={1}\t",a,b);
10 10 Console.Read();
11 11 }
12 12 //交換a,b兩個變量的值
13 13 private static void Swap(int a,int b)
14 14 {
15 15 int temp = a;
16 16 a = b;
17 17 b = temp;
18 18 Console.WriteLine("方法內\ta={0}\tb={1}\t",a,b);
19 19 }
20 20 }
View Code
運行結果:
交換前 a = 1 b = 2
方法內 a = 2 b = 1
交換後 a = 1 b = 2
並未達到我們的需求!
原因分析:int類型為值類型,它存在於線程的堆棧中。當調用Swap(a,b)方法時,相當於把a,b的值(即1,2)拷貝一份,然後在方法內交換這兩個值。交換完後,a還是原來的a,b還是原來的b。這就是C#中按值傳遞的原理,傳遞的是變量所對應數據的一個拷貝,而非引用。
修改代碼如下即可實現我們想要的結果:

1 class Program
2 2 {
3 3 static void Main(string[] args)
4 4 {
5 5 int a = 1;
6 6 int b = 2;
7 7 Console.WriteLine("交換前\ta={0}\tb={1}\t",a,b);
8 8 Swap(ref a,ref b);
9 9 Console.WriteLine("交換後\ta={0}\tb={1}\t",a,b);
10 10 Console.Read();
11 11 }
12 12 //交換a,b兩個變量的值
13 13 private static void Swap(ref int a, ref int b)
14 14 {
15 15 int temp = a;
16 16 a = b;
17 17 b = temp;
18 18 Console.WriteLine("方法內\ta={0}\tb={1}\t",a,b);
19 19 }
20 20 }
View Code
1 關於重載
原則:有out|ref關鍵字的方法可以與無out和ref關鍵字的方法構成重載;但如想在out和ref間重載,編譯器將提示:不能定義僅在ref和out的上的方法重載
2 關於調用前初始值
原則:ref作為參數的函數在調用前,實參必須賦初始值。否則編譯器將提示:使用了未賦值的局部變量;
out作為參數的函數在調用前,實參可以不賦初始值。
3 關於在函數內,引入的參數初始值問題
原則:在被調用函數內,out引入的參數在返回前至少賦值一次,否則編譯器將提示:使用了未賦值的out參數;
在被調用函數內,ref引入的參數在返回前不必為其賦初值。
總結:C#中的ref和out提供了值類型按引用進行傳遞的解決方案,當然引用類型也可以用ref和out修飾,但這樣已經失去了意義。因為引用數據類型本來就是傳遞的引用本身而非值的拷貝。ref和out關鍵字將告訴編譯器,現在傳遞的是參數的地址而不是參數本身,這和引用類型默認的傳遞方式是一樣的。同時,編譯器不允許out和ref之間構成重載,又充分說明out和ref的區別僅是編譯器角度的,他們生成的IL代碼是一樣的。有人或許疑問,和我剛開始學習的時候一樣的疑惑:值類型在托管堆中不會分配內存,為什麼可以按地址進行傳遞呢?值類型雖然活在線程的堆棧中,它本身代表的就是數據本身(而區別於引用數據類型本身不代表數據而是指向一個內存引用),但是值類型也有它自己的地址,即指針,現在用ref和out修飾後,傳遞的就是這個指針,所以可以實現修改後a,b的值真正的交換。這就是ref和out給我們帶來的好處。
關於更多如This,Base等下次再分享
const 的概念就是一個包含不能修改的值的變量。
常數表達式是在編譯時可被完全計算的表達式。因此不能從一個變量中提取的值來初始化常量。
如果 const int a = b+1;b是一個變量,顯然不能再編譯時就計算出結果,所以常量是不可以用變量來初始化的。
readonly 允許把一個字段設置成常量,但可以執行一些運算,可以確定它的初始值。
因為 readonly 是在計算時執行的,當然它可以用某些變量初始化。
readonly 是實例成員,所以不同的實例可以有不同的常量值,這使readonly更靈活。
readonly 關鍵字與 const 關鍵字不同。
1. const 字段只能在該字段的聲明中初始化。
readonly 字段可以在聲明或構造函數中初始化。因此,根據所使用的構造函數,readonly 字段可能具有不同的值。
2. const 字段是編譯時常數,而 readonly 字段可用於運行時常數。
3. const 默認就是靜態的,而 readonly 如果設置成靜態的就必須顯示聲明。
4.const 對於引用類型的常數,可能的值只能是 string 和 null。
readonly可以是任何類型
* 需要注意的一個問題是:
對於一個 readonly 的 Reference 類型,只是被限定不能進行賦值(寫)操作而已。而對其成員的讀寫仍然是不受限制的。
public static readonly Class1 my = new Class1();
…
my.SomeProperty = 10; //正常
my = new Class1(); //出錯,該對象是只讀的
但是,如果上例中的 Class1 不是一個 Class 而是一個 struct,那麼後面的兩個語句就都會出錯。
static readonly:
Java 中 static 是當載入一個類時執行一次的。
C#中是怎麼執行的,我沒有查到。很奇怪幾乎每本java的書都會說static的問題,C#的往往只說怎麼用,但是應該是在main函數調用之前初始化,所以static readonly也是運行時的,可以用變量付值,如:
private static readonly string path = System.Windows.Forms.Application.StartupPath + “aaa”;
const 的概念就是一個包含不能修改的值的變量。
常數表達式是在編譯時可被完全計算的表達式。因此不能從一個變量中提取的值來初始化常量。
如果 const int a = b+1;b是一個變量,顯然不能再編譯時就計算出結果,所以常量是不可以用變量來初始化的。
readonly 允許把一個字段設置成常量,但可以執行一些運算,可以確定它的初始值。
因為 readonly 是在計算時執行的,當然它可以用某些變量初始化。
readonly 是實例成員,所以不同的實例可以有不同的常量值,這使readonly更靈活。
readonly 關鍵字與 const 關鍵字不同。
1. const 字段只能在該字段的聲明中初始化。
readonly 字段可以在聲明或構造函數中初始化。因此,根據所使用的構造函數,readonly 字段可能具有不同的值。
2. const 字段是編譯時常數,而 readonly 字段可用於運行時常數。
3. const 默認就是靜態的,而 readonly 如果設置成靜態的就必須顯示聲明。
4.const 對於引用類型的常數,可能的值只能是 string 和 null。
readonly可以是任何類型
總結
const只能在初期就使用常量初始化好。對於每一次編譯後的結果,const的值是固定的,而readonly的值是可以在運行的時候才確定值的~~