posts - 56,  comments - 12,  trackbacks - 0
                                            1 緒論
          c# 是一種簡練,時髦(?),面向對象(object oriented),類型可靠(type-safe)的
          編程語言。它(發音:C sharp)是從c/c++發展而來的(?俺覺得更象是java),和c/c++
          是一個語系。所以,很容易被c/c++的程序員接受。c#的目標是結合Visual Basic的高產和
          C++質樸的力量。

          c#將會是vs7的一分子。vs7還支持vb,vc和標記語言——VBScript和JScript。所有這些語言
          都會在Next Generation Windows Services (NWGS) platform 中得到支持(c#就需要一個
          NWGS SDK包,可以在m$的網站上下載)。有了這個東東(NWGS),c#就不需要自己的類庫,
          而使用vc或vb這樣一些成熟的庫。c#也確實沒有自己的類庫。
          廢話完了。

          1。1 一個老土的例子(就不能換換嗎?)*/
          /* idontlikeHelloworld.cs : such a out sample :( */
          1: using System;
          2: class idontlikeHelloworld
          3: {
          4: static void Main() {
          5: Console.WriteLine("i dont like Hello world");
          6: Console.ReadLine();
          7: }
          8: }
          /* 如果俺要出書的話,會考慮換個好點的例子。 ^&^

          先說說怎樣運行。首先,你需要windows2000!(是的,就是它,請各位不要隨地丟果皮——
          整個香蕉丟給俺就可以了。)然后,需要NWGS SDK!(82.4mb,不算很大噢。嘿嘿,好在
          它沒有自己的類庫。)安裝后,在你的程序所在的目錄下鍵入:

          csc idontlikeHelloworld.cs (加上一個回車鍵)

          是不是有點復古的味道?這個操作會在和你的*.cs相同目錄下產生一個
          idontlikeHelloworld.exe文件。雙擊它,距可以看見:

          i dont like Hello world

          回車就可以結束它,非常簡單。不過,也可以這樣:把它存成后綴為.c的文件更好
          (即:idontlikeHelloworld.c)。這樣就可以用vc的IDE進行打字,編輯。vc的
          txt editor是最棒的噢(又要vc,NO!!!)。然后:

          csc idontlikeHelloworld.c (加上一個回車鍵)

          最終效果是完全一樣的。好,現在分析語法:(c#在語法上完全沒有新意 :-| )

          1: using System;

          using 其實是c++的關鍵字,在c#中的含義也相仿(就是說俺還不敢100%肯定,抱歉)。using
          用在另一個關鍵字namespace之后。還是先看看namespace。
          語法(syntax):(from MSDN)

          namespace [identifier] { namespace-body }

          俺的理解:
          identifier:在這里就是System(請記住:c#和c/c++一樣,是區分大小寫的!)。System
                      必須在使用它的范圍內是唯一的。即,不能夠有第二個System,但可以有system。
                      而“它的范圍”,俺不想詳細解說,只有在實踐中才可能掌握。而且,初學者根本
                      不必知道!俺也是近來才知道還有個namespace和using。 :)

          在{ namespace-body }中的是真正有用的東東,包括第五行的“Console.WriteLine”的聲明和
          定義(后面還會提到)。System是由NWGS定義的,咱們只需用(using)它即可。至于System在
          什么文件里定義,咱就不用管了!交給編譯器(就是剛才那個“csc.exe”)去尋找。這就代替
          了c/c++中的“#i nclude”,可以說是近了一步,避免大量煩人的細節。如果你沒學過c/c++,
          就不用理會。namespace 在后面還會談到。

          2: class idontlikeHelloworld

          class:是c語系中另一個關鍵字“類”。表示一系列的特性(官方說法:屬性)和行為方法,有
          了它你的程序就可以“另類”,創造與別不同的有你特色的東東噢!在這里,俺就定義了
          “idontlikeHelloworld”。注意:這也是c#強制的,對于每一個可執行的程序都必須有。你想干
          的事就可以記錄在緊跟著你定義的class后面的一對花括號。注意:“{”和“}”一一對應的,
          “(”和“)”同樣。

          4: static void Main() {

          Main()是本例子第一個動作(行為方法),干的第一件事。它是屬于俺定義的idontlikeHelloworld
          類的方法。并且是c#強制的,是程序的真正開始!在緊跟在它后面的“{}”中的語句順序,就是程序
          的運行順序!本例中只有一行(第六行干嘛用?你可以去掉再編譯一次看看),輸出一句話。

          5: Console.WriteLine("i dont like Hello world");

          非常奇怪,Console(再次提醒:注意大小寫)不是俺定義的,從何而來?它其實是屬于System
          namespace 的一個class。WriteLine()是Console類中的一個方法,用來顯示一句話(字符串)。
          這里只是用了這個方法的1/18!并且是最簡單之一!其他的有機會再說。你也可以用
          “Console.WriteLine”在“NGWS SDK Documentaion”中搜索“Console.WriteLine”,記住復選
          “僅搜索標題”,它會列出19項。好啦,完了!其實,還有“.”沒說呢!呵呵...lei si la!!!!
          (續前)
          “.”被稱為分隔符(separator),用來連接名字,如上面的“Console.WriteLine”,就把類和它的
          方法連接。通過這種方式,咱們就可以使用現成方法集合。這里再回顧一下俺的例子,看看namespace和
          “.”是如何連用的,還有為什么要使用namespace這個關鍵字。把例子稍微改一下:*/
          /* idontlikeHelloworld.cs */
          1: //using System;
          2: class idontlikeHelloworld
          3: {
          4: static void Main() {
          5: System.Console.WriteLine("i dont like Hello world");
          6: System.Console.ReadLine();
          7: }
          8: }

          /* 看見了,當俺注銷掉“using System;”后,在第五行和第六行加了“System”。程序的結果不會改
          變。但是,很明顯的這樣比較羅嗦,所以引入了“namespace”。其實,class應該可以完成同樣的功能。
          不過,設計者可能不想讓一個關鍵字涵蓋太多的功能。記得在c向c++發展的時候,引入了“class”,而
          不是擴展“struct”關鍵字的功能;又比如“=”只用于賦值,“==”只用于判斷相等。這是c/c++和c#
          在語法上其中一個重要的特點。這樣設計的好處很多。有機會再聊噢。
          如果你沒學過c/c++,以下的內容可以跳過。c#與c/c++在語法上還是有區別的,比如:
          1。c#根本沒有“::”;“->”只在程序中很小的片斷中。在c#中應采用“.”。
          2。c#無須先聲明定義,再使用。與java相同。
          3。c#取消了用“#i nclude”導入其他的程序文本文件,而采用象征性的句柄引入他人的代碼。這樣一來,
             就排除了編程語言間的障礙,方便地使用其它語言編寫的庫。如“Console”類可以是c#或者是其他任一種語言編寫的。

          1。2 自動化的內存管理(Automatic memory management)
          手動管理內存需要程序員自行分配和釋放內存塊。這要求程序員有清晰的頭腦和對整個運行過程有十分的
          把握(好難!)。而c#把程序員從這難以承擔的任務中解放出來。在多數的情況下,這種自動內存管理提
          高代碼的質量和程序員的生產力。并且,不會對程序的意圖和執行產生幅面的影響(?俺可不相信m$的鬼
          話)。不過,估計比java的回收站好一點吧。因為c#出道遲嘛(盡胡扯)。好了,來看看例子。*/

          using System;
          public class Stack
          {
            private Node first = null;
            public bool Empty {
              get {
                    return (first == null);
                  }
            }
            public object Pop() {
              if (first == null)
                throw new Exception("Can't Pop from an empty Stack.");
              else {
                      object temp = first.Value;
                      first = first.Next;
                      return temp;
                   }
            }
            public void Push(object o) {
              first = new Node(o, first);
            }
            class Node
            {
              public Node Next;
              public object Value;
              public Node(object value): this(value, null) {}
              public Node(object value, Node next) {
                Next = next;
                Value = value;
              }
            }
          }

          class Test
          {
            static void Main() {
              Stack s = new Stack();
              for (int i = 0; i < 10; i++)
                s.Push(i);
              while (!s.Empty)
                Console.WriteLine(s.Pop());
            }
          }
          /*
          stack類實現了一系列Node的實例。大家可以看看stack類的Push方法。Node的實例就是在Push方法中創建的。
          就是“first = new Node(o, first);”。請記住這個“new”噢。它就是用來創建類實例的。相關的語法太
          多,遛到后面用一節詳細講。這里只是要了解自動內存管理(Automatic memory management)好處?!“new”
          是負責初始化類實例。而在c/c++中釋放這些實例要用另一個關鍵字“delete”。但是在什么時候用delete呢,
          這通常是很費神的活,老手也會陰溝里翻船。何況是俺呢!但在c#中有不用了。例子里就沒有用“delete”。
          當Node的實例不需要時,垃圾收集器(garbage collector)自動銷毀它,不用俺操心嘍。這點到和java挺
          像的(可能是抄的)。

          在一個test類里,俺用了一個循環,對stack類的實例的Push方法賦值十次。于是,Push創建了Node的十個實
          例(instance)。然后用Pop把它們顯示出來。其順序正好與創建的順序相反。
          這個例子相當的好,是stack
          的一個典型,也很好的表述了自動內存管理的機制。但也不好懂,好在這一節不是寫給毫無基礎的網友看的。
          俺自個都花了幾分鐘看明白,各位大蝦更是沒問題。

          其實,當顯示完了“10”以后,就會有一個Node的實例符合被釋放的條件,但垃圾收集器并不一定會這樣做。
          也就是說,它的行為并不確定(這和java一樣,俺猜)。有時候,這種行為會帶來一些負面影響。起碼是性
          能降低。自動內存管理本身也是有問題的。因為它很難管理一些特殊情況。有一些關于java的垃圾收集器的
          文章也有提到。m$也不會好得了多少。所以,m$有個不安全代碼的術語(unsafe code),用來為高級用戶服
          務。即,用戶可以不采用垃圾收集器。但必須用“unsafe”關鍵字顯式聲明之。這樣就避免了用戶不經意以
          外使用不安全代碼。下面是一個例子:*/

          using System;
          class Test
          {
            unsafe static void WriteLocations(byte[] arr) {
              fixed (byte *p_arr = arr) {
                byte *p_elem = p_arr;
                for (int i = 0; i < arr.Length; i++) {
                  byte value = *p_elem;
                  string addr = int.Format((int) p_elem, "X");
                  Console.WriteLine("arr[{0}] at 0x{1} is {2}", i,  addr, value);
                  p_elem++;
                }
              }
            }
            static void Main() {
              byte[] arr = new byte[] {1, 2, 3, 4, 5};
              WriteLocations(arr);
            }
          }
          /*
          俺對這個例子不是很滿意,也讓俺有點迷惑,有機會再自己寫一個。很簡單,只是可以用指針了!萬歲!
          其實,俺對這一節最沒有把握了!有不少地方都不能自圓其說!所以,請各位大蝦大力批評。*/

          1。3 類型 
          c#支持兩種基本的類型:一種是值(value types),一種是引用(reference types)。值包括簡單類型
          (char、int、和float),枚舉(enum)和結構(struct)。引用包括類(class),界面(interface),
          代表(delegate)和數組陣列(array)。值與引用不同之處在于:值直接存儲它的數據內容;而引用存儲對象
          的引用。是不是粉費解?!打個比方吧。你在某地買了套別墅(好棒噢)。卻從未去過,只知道地址,怎
          么辦?你可以坐出租車,司機看了地址就知道怎樣走不用你操心。你手里的地址就好像對象的名字,你把
          它寫在程序中,就好像把地址給了司機。司機就是你的編譯器,它知道該去哪。你豪華的房子就好比那個
          NGWS SDK開發包(82mb噢,夠豪華了!俺的m啊--就這樣燒嘍)。房子里有你想要的東東,比如你想寫一句
          話(i dont like Hello world),就好像上面例子,要用到“WriteLine”。于是,你就給出“WriteLine”
          的地址,比如:“Console.WriteLine”。明白?!俺可累了。zzz...  (強打精神)不知道你想到沒有,
          值和引用的區別可以引出一個重要特性。值的變量和變量存儲的數據是一一對應的,唯一性。而引用則不
          然。引用中不同的變量可以引用同一個對象的實例。當其中一個變量改變實例的值時,其他引用這個實例的
          變量也會受到影響(當然,變量本身并沒有改變,即,地址沒變)。瞧,變量只是說明存儲對象的位置(地
          址),而不是對象本身。就好像你漂亮的房子被燒了,但你的地址并沒有改變,但地址對應的房子就沒了。
          也許是別人也有這個地址,他去燒了你的房子!好了,在給個例子:*/

          1: using System;
          2: class CValue
          3: {
          4: public int Value = 0;
          5: }
          6: class Test
          7: {
          8: static void Main() {
          9: int val1 = 0;
          10: int val2 = val1;
          11: val2 = 123;
          12: CValue ref1 = new CValue();
          13: CValue ref2 = ref1;
          14: ref2.Value = 123;
          15: Console.WriteLine("Values: {0}, {1}", val1, val2);
          16: Console.WriteLine("Refs: {0}, {1}", ref1.Value, ref2.Value);
          17: }
          18: }

          /* 下面是輸出的結果:
          Values: 0, 123
          Refs: 123, 123

          啊哈,應該粉清楚了吧。變量val1和變量val2互不影響,它們各自有自己的存儲空間。而ref2復制
          了ref1,所以,它們引用了同一個對象的實例。當改變它們其中一個的時候,就會影響到另一個的
          值。
          1。5 數組類型(Array types) 

          數組可以是一維的,也可是多維的。數祖的成員可以是整齊的,也可以是變長(jagged)的。

          一維的數組是最普通,最簡單的。這里值給出一個例子,就不多解釋了。*/
          using System;
          class Test
          {
           static void Main() {
            int[] arr = new int[5];
            for (int i = 0; i < arr.Length; i++)
             arr[i] = i * i;
            for (int i = 0; i < arr.Length; i++)
             Console.WriteLine("arr[{0}] = {1}", i, arr[i]);
           }
          }

          /* 結果如下:
          arr[0] = 0
          arr[1] = 1
          arr[2] = 4
          arr[3] = 9
          arr[4] = 16

          我們還可以比較的看看多維,規則,變長的數組的定義和賦值:*/
          class Test
          {
           static void Main() {
            int[] a1 = new int[] {1, 2, 3};                     //一維
            int[,] a2 = new int[,] {{1, 2, 3}, {4, 5, 6}};      //二維
            int[,,] a3 = new int[10, 20, 30];                   //三維
            int[][] j2 = new int[3][];                          //變長
            j2[0] = new int[] {1, 2, 3};
            j2[1] = new int[] {1, 2, 3, 4, 5, 6};
            j2[2] = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
           }
          }
          /*
          上面的例子給出了各種樣式的數組。變量a1、a2和a3是規則數組。j2則是變長的數組。
          規則數組很容易就可以計算出它們的長度。比如a3的長度是:10*20*30=6000。相反,變長
          數組就有點不同,它的每一個維度都必須單獨定義。如j2的第一維度是3,第二個是6,第
          三個是9,所以總長度是:1*3+1*6+1*9=18。

          上面對數組的賦值是嚴謹的風格,在某種情況下,我們可以簡化寫法,但我總覺得這種簡化
          應用限制太多,容易出錯。在這里就不作介紹了。這里再給一個例子說明函數中的參數如何
          賦值*/
          class Test
          {
           static void F(long[] arr) {}
           static void Main() {
            F(new longt[] {1, 2, 3});
           }
          }
          趕出一編!請指正! 
          1。6 統一系統類型(Type system unification)
          c#獨創了一種類型——統一系統類型(為了這個累刑,我頭疼死了。誰有更好的名字,請務必告訴
          我)。總之,所有的其他類型,包括值和引用,都可以被當作統一系統類型來對待。從概念上說,
          所有的類型都從它派生。這樣,其他的類型就可以使用統一系統類型的屬性和方法。包括一些“簡
          單”類型,如:int。還是給個例子吧:*/
          using System;
          class Test
          {
            static void Main() {
              Console.WriteLine(3.ToString());
            }
          }
          /*“3.ToString()”調用了object的“ToString()”方法。相信學過c/c++的朋友都知道要輸出一個
          數字有多麻煩,現在就省事了。再看一個:*/
          class Test
          {
            static void Main() {
              int i = 123;
              object o = i;    // boxing
              int j = (int) o;  // unboxing
            }
          }
          /* 這個像帽子戲法的例子中,從“int”轉換成“object”,又轉換回來。這樣一來,在值和引用
          之間就架起了一座橋梁。這樣有什么用呢。即興舉一個常見的例子...就min把。在c/c++中:*/
          // c/c++ code

          void min(int i, int j)
          {
            return ((i < j) ? i : j);
          }

          /* 如果比較的不是int,或者說可能是int,也可能是float、double呢?可以這樣:*/

          template<class T>
          T min (T i, T j)
          {
            return ((i < j) ? i : j)
          }

          /* 用c#可以:*/
          void swap (object a, object b)
          {
            return ((i < j) ? i : j);
          }

          /* 我想大家一定看出來第二個例子要比較一個int和一個float的話,還需要一些轉換,而第三個
          例子就可以比較所有的變量!這個靈活度簡直太大了。所以,我私以為,大家使用時一定要小心!
          它在比較一個int和一個class的時候決不會報錯的。呵呵,我發現我的翻譯總是越跑越遠,總是
          扣不住原文。篡改甚多,敬請原諒!
           
          1。7 語句(Statements) 

          c#借用了c/c++大多數的語句方法,不過仍然有些值得注意的地方。還有些地方是有所改動的。
          在這里,我只提一些c#特有的東東。

          1。7。10 “foreach”語句
          “foreach”語句列舉一個集合內的所有元素,并對這些元素執行一系列的操作。還是看看例子吧:*/

          using System;
          using System.Collections;
          class Test
          {
            static void WriteList(ArrayList list) {
              foreach (object o in list)
              {
                int i = (int) o;//如果是for語句,這里一定會報錯!
                Console.WriteLine(0);
                Console.WriteLine(++i);
              }
            }
            static void Main() {
              ArrayList list = new ArrayList();
              for (int i = 0; i < 10; i++)
                list.Add(i);
              WriteList(list);
            }
          }
          /*這個例子用“foreach”掃描了整個“list”,并把“list”中所有的元素打印出來。有時候還是
          挺方便的。

          1。7。15 安全檢查開關(The checked and unchecked statements)
          “checked”和“unchecked”語句用來控制數學運算和完整類型轉換的檢查工作。“checked”檢查它
          作用的域中可能出現的違例,并拋出一個異常;而“unchecked”則阻止所有的檢查。舉個例子:*/

          using System;
          class Test
          {
             static int x = 1000000;
             static int y = 1000000;
             static int F() {
                checked {return (x * y);}     // 拋出 OverflowException
             }
             static int G() {
                unchecked {return (x * y);}   // 返回 -727379968
             }
             static int H() {
                return x * y;              // 缺省狀態。
             }
             static void Main() {
               F();                        //可以注銷掉此行試試。
               Console.WriteLine(G());
               Console.WriteLine(H());
             }
          }

          /*
          在編譯過程中不會有任何錯誤出現。因為“checked”和“unchecked”只在運行時才起作用。值得一說的是
          H()。它的缺省狀態和編譯器當前的缺省溢出檢查的狀態有關。但返回的結果肯定和F()或G()中的任一個相同。
          再看一個例子:*/

          using System;
          class Test
          {
             const int x = 1000000;
             const int y = 1000000;
             static int F() {
                checked {return (x * y);}    // 編譯器警告(Compile warning):溢出(overflow)
             }
             static int G() {
                unchecked {return (x * y);}  // 返回 -727379968
             }
             static int H() {
                return x * y;                // 編譯器警告(Compile warning):溢出(overflow)
             }
             static void Main() {
               Console.WriteLine(F());       //可以注銷掉此行試試。
               Console.WriteLine(G());
               Console.WriteLine(H());       //可以注銷掉此行試試。
             }
          }

          /* 當F()和H()求值的時候,就會引起一個編譯警告。而在G()中,因為有了“unchecked”,屏蔽了這個警
          告。要注意的是“checked”和“unchecked”都不能對函數的返回值進行操作!比如:*/
          class Test
          {
             static int Multiply(int x, int y) {
                return x * y;
             }
             static int F() {
                checked{ return Multiply(1000000, 1000000); } // 與 return Multiply(1000000, 1000000);
             }                                                // 有相同的效果。
          }
          /* 其實大家稍微想一下知道為什么m$沒有這么做!對這個內容的討論超出本文的范圍和俺的能力之外哦。

          在c#中,所有的十六進制數都是uint。如果用強制類型轉換會引起編譯器報錯。用“unchecked”則可以
          跳過這個機制,把uint的十六進制數轉化為int。如:*/

          class Test
          {
             public const int AllBits = unchecked((int)0xFFFFFFFF);
             public const int HighBit = unchecked((int)0x80000000);
          }

          /* 上例所有的常數都是uint,而且超過了int的范圍,沒有“unchecked”,這種轉換會引發一個編譯器錯
          誤。注意:上面用的是“unchecked”操作符。不是語句。不過它們之間除了一個用“()”,另一個用
          “{}”以外,幾乎一樣。BTW,“checked”同樣。

          1。7。16 “lock”語句(The lock statement)
          “lock”獲得一個相互排斥的對象鎖定。(俺查過一些資料,但都沒有清晰說明,暫不介紹)


          苦笑枯 2007-01-19 00:14 發表評論

          文章來源:http://www.aygfsteel.com/kuxiaoku/articles/94806.html
          posted on 2007-01-19 00:14 苦笑枯 閱讀(317) 評論(0)  編輯  收藏 所屬分類: C#
          收藏來自互聯網,僅供學習。若有侵權,請與我聯系!

          <2007年1月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          常用鏈接

          留言簿(2)

          隨筆分類(56)

          隨筆檔案(56)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 小金县| 万全县| 招远市| 蓝田县| 建湖县| 沙坪坝区| 安义县| 尚义县| 台前县| 牟定县| 满洲里市| 南康市| 白城市| 淮北市| 西林县| 凌云县| 元谋县| 惠州市| 巴东县| 井研县| 福州市| 龙海市| 教育| 乳源| 房山区| 郧西县| 龙井市| 石楼县| 梓潼县| 萝北县| 莎车县| 苍梧县| 瓦房店市| 江安县| 左云县| 漯河市| 阆中市| 山阳县| 治县。| 廉江市| 娄底市|