熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

最簡單的C#快速入門教程

2022-06-13   來源: .NET編程 

  在一小時內學會 C#使用例程簡單卻完整的探索 C# 語言的構造和特點本文特別適合有 C++ 基礎卻沒有太多精力學習 C# 的讀者

  關於作者

  Aisha Ikram

  我現在在英國一家軟件公司任技術帶頭人我是計算機科學的碩士我主要使用 NET / C# VBNET ASPNET VC++ MFC ATL COM/DCOM SQL Server /最近我在學習 NET x 的全部內容我的免費源代碼和文章網站是
職業團隊帶頭人
位置英國

  簡介

  C# 是一種具有 C++ 特性Java 樣式及 BASIC 快速建模特性的編程語言如果你已經知曉 C++ 語言本文將在不到一小時的時間內帶你快速浏覽 C# 的語法如果熟悉 Java 語言Java 的編程結構打包和垃圾回收的概念肯定對你快速學習 C# 大有幫助所以我在討論 C# 語言構造的時候會假設你知道 C++

  本文通過一系列例程以簡短但全面的方式討論了 C# 語言構造和特性所以你僅需略覽代碼片刻即可了解其概念

  注意本文不是為 C# 宗師而寫有很多初學者的 C# 文章這只是其中之一

  接下來關於 C# 的討論主題

  編程結構
    命名空間
    數據類型
    變量
    運算符與表達式
    枚舉
    語句
    類與結構
    修飾符
    屬性
    接口
    函數參數
    數組
    索引器
    裝箱與拆箱
    委托
    繼承與多態

以下主題不會進行討論

  C++ 與 C# 的共同點
    諸如垃圾回收線程文件處理等概念
    數據類型轉換
    異常處理
    NET 庫

  編程結構

  和 C++ 一樣C# 是大小寫敏感的半角分號(;)是語句分隔符和 C++ 有所區別的是C# 中沒有單獨的聲明(頭)和實現(CPP)文件所有代碼(類聲明和實現)都放在擴展名為 cs 的單一文件中

  看看 C# 中的 Hello World 程序
復制內容到剪貼板


代碼:
 using System;

  namespace MyNameSpace

  {

  class HelloWorld

  {
    static void Main(string[] args)
    {
        ConsoleWriteLine (Hello World);
    }
}

        C# 中所有內容都打包在類中而所有的類又打包在命名空間中(正如文件存與文件夾中)和 C++ 一樣有一個主函數作為你程序的入口點C++ 的主函數名為 main而 C# 中是大寫 M 打頭的 Main

  類塊或結構定義之後沒有必要再加一個半角分號C++ 中是這樣但 C# 不要求

  命名空間

  每個類都打包於一個命名空間命名空間的概念和 C++ 完全一樣但我們在 C# 中比在 C++ 中更加頻繁的使用命名空間你可以用點()定界符訪問命名空間中的類上面的 Hello World 程序中MyNameSpace 是其命名空間

  現在思考當你要從其他命名空間的類中訪問 HelloWorld 類
復制內容到剪貼板
代碼:
 using System;
namespace AnotherNameSpace
{   
    class AnotherClass
    {
        public void Func()
        {
            ConsoleWriteLine (Hello World);
        }
    }
}
現在在你的 HelloWorld 類中你可以這樣訪問
復制內容到剪貼板
代碼:
 using System;
using AnotherNameSpace; // 你可以增加這條語句
namespace MyNameSpace
{
class HelloWorld
{
    static void Main(string[] args)
    {
        AnotherClass obj = new AnotherClass();
        objFunc();
    }
}
}
NET 庫中System 是包含其他命名空間的頂層命名空間默認情況下存在一個全局命名空間所以在命名空間外定義的類直接進到此全局命名空間中因而你可以不用定界符訪問此類
你同樣可以定義嵌套命名空間

  Using

  #include 指示符被後跟命名空間名的 using 關鍵字代替了正如上面的 using SystemSystem 是最基層的命名空間所有其他命名空間和類都包含於其中System 命名空間中所有對象的基類是 Object

  變量

  除了以下差異C# 中的變量幾乎和 C++ 中一樣

      C# 中(不同於 C++)的變量總是需要你在訪問它們前先進行初始化否則你將遇到編譯時錯誤故而不可能訪問未初始化的變量
    你不能在 C# 中訪問一個掛起指針
    超出數組邊界的表達式索引值同樣不可訪問
    C# 中沒有全局變量或全局函數取而代之的是通過靜態函數和靜態變量完成的

  數據類型
所有 C# 的類型都是從 object 類繼承的有兩種數據類型

      基本/內建類型
    用戶定義類型

  以下是 C# 內建類型的列表

  類型        字節        描述
byte                  unsigned byte
sbyte                signed byte
short                signed short
ushort                unsigned short
int                  signed integer
uint                  unsigned integer
long                  signed long
ulong                unsigned long
float                floating point number
double                double precision number
decimal              fixed precision number
string                Unicode string
char                  Unicode char
bool        true false boolean

  注意C# 的類型范圍和 C++ 不同例如long 在 C++ 中是 字節而在 C# 中是 字節bool 和 string 類型均和 C++ 不同bool 僅接受真假而非任意整數

  用戶定義類型文件包含

      類 (class)
    結構(struct)
    接口(interface)

  以下類型繼承時均分配內存

      值類型
    參考類型

  值類型

  值類型是在堆棧中分配的數據類型它們包括了

  ?    除字符串所有基本和內建類型
?    結構
?    枚舉類型

  引用類型

  引用類型在堆(heap)中分配內存且當其不再使用時將自動進行垃圾清理和 C++ 要求用戶顯示創建 delete 運算符不一樣它們使用新運算符創建且沒有 delete 運算符在 C# 中它們自動由垃圾回收系統回收

  引用類型包括

  ?    類
?    接口
?    集合類型如數組
?    字符串

  枚舉

  C# 中的枚舉和 C++ 完全一樣通過關鍵字 enum 定義

  例子
復制內容到剪貼板
代碼:
enum Weekdays
{
    Saturday Sunday Monday Tuesday Wednesday Thursday Friday
}
類與結構

  除了內存分配的不同外類和結構就和 C++ 中的情況一樣類的對象在堆中分配並使用 new 關鍵字創建而結構是在棧(stack)中進行分配C# 中的結構屬於輕量級快速數據類型當需要大型數據類型時你應該創建類

  例子
復制內容到剪貼板
代碼:
 struct Date
{
    int day;
    int month;
    int year;
}
       
class Date
{
    int day;
    int month;
    int year;
    string weekday;
    string monthName;
    public int GetDay()
    {
        return day;
    }
    public int GetMonth()
    {
        return month;
    }
    public int GetYear()
    {
        return year;
    }
    public void SetDay(int Day)
    {
        day = Day ;
    }
    public void SetMonth(int Month)
    {
        month = Month;
    }
    public void SetYear(int Year)
    {
        year = Year;
    }
    public bool IsLeapYear()
    {
        return (year/ == );
    }
    public void SetDate (int day int month int year)
    {
    }
   
}

  屬性

  如果你熟悉 C++ 面向對象的方法你一定對屬性有自己的認識對 C++ 來說前面例子中 Date 類的屬性就是 daymonth 和 year而你添加了 Get 和 Set 方法C# 提供了一種更加便捷簡單而又直接的屬性訪問方式

  所以上面的類應該寫成這樣
復制內容到剪貼板
代碼:
using System;
class Date
{
    public int Day{
        get {
            return day;
        }
        set {
            day = value;
        }
    }
    int day;

  public int Month{
        get {
            return month;
        }
        set {
            month = value;
        }
    }
    int month;

  public int Year{
        get {
            return year;
        }
        set {
            year = value;
        }
    }
    int year;

  public bool IsLeapYear(int year)
    {
        return year%== ? true: false;
    }
    public void SetDate (int day int month int year)
    {
        thisday = day;
        thismonth = month;
        thisyear = year;
    }
}
這裡是你 get 和 set 屬性的方法
復制內容到剪貼板
代碼:
class User
{
  public static void Main()
  {
        Date date = new Date();
        dateDay = ;
        dateMonth = ;
        dateYear = ;
        ConsoleWriteLine
        (Date: {}/{}/{} dateDay dateMonth dateYear);
    }
}
修飾符

  你必須知道 C++ 中常用的 publicprivate 和 protected 修飾符我將在這裡討論一些 C# 引入的新的修飾符

  readonly

  readonly 修飾符僅用於修飾類的數據成員正如其名字說的一旦它們已經進行了寫操作直接初始化或在構造函數中對其進行了賦值readonly 數據成員就只能對其進行讀取readonly 和 const 數據成員不同之處在於 const 要求你在聲明時進行直接初始化看下面的例程
復制內容到剪貼板

  代碼:
class MyClass
{
    const int constInt = ; //直接進行
    readonly int myInt = ; //直接進行
    readonly int myInt;
   
    public MyClass()
    {
        myInt = ;        //間接進行
    }
    public Func()
    {
        myInt = ; //非法
        ConsoleWriteLine(myIntToString());
    }
}
sealed

  帶有 sealed 修飾符的類不允許你從它繼承任何類所以如果你不想一個類被繼承你可以對該類使用 sealed 關鍵字
復制內容到剪貼板
代碼:
sealed class CanNotbeTheParent
{
    int a = ;
}
unsafe

  你可以使用 unsafe 修飾符在 C# 中定義一個不安全上下文在不安全上下文中你可以插入不安全代碼如 C++ 的指針等參見以下代碼
復制內容到剪貼板
代碼:
public unsafe MyFunction( int * pInt double* pDouble)
{
    int* pAnotherInt = new int;
    *pAnotherInt  = ;
    pInt = pAnotherInt;
   
    *pDouble = ;   
}
接口

  如果你有 COM 的思想你馬上就知道我在說什麼了接口是只包含函數簽名而在子類中實現的抽象基類在 C# 中你可以用 interface 關鍵字聲明這樣的接口類NET 就是基於這樣的接口的C# 中你不能對類進行多重繼承——這在 C++ 中是允許的通過接口多重繼承的精髓得以實現即你的子類可以實現多重接口(譯注由此可以實現多重繼承)
復制內容到剪貼板
代碼:
using System;
interface myDrawing
{
    int originx
    {
        get;
        set;
    }
    int originy
    {
        get;
        set;
    }
    void Draw(object shape);           
}

  class Shape: myDrawing
{
    int OriX;
    int OriY;
   
    public int originx
    {
        get{
            return OriX;
        }
        set{
            OriX = value;
        }
    }
    public int originy
    {
        get{
            return OriY;
        }
        set{
            OriY = value;
        }
    }
    public void Draw(object shape)
    {
        // 做要做的事
    }
   
    // 類自身的方法
    public void MoveShape(int newX int newY)
    {
   
    }       
   
}
數組

  數組在 C# 中比 C++ 中要高級很多數組分配於堆中所以是引用類型的你不能訪問數組邊界外的元素所以 C# 防止你引發那種 bug同時也提供了迭代數組元素的幫助函數foreach 是這樣的迭代語句之一C++ 和 C# 數組的語法差異在於

  方括號在類型後面而不是在變量名後面
創建元素使用 new 運算符
C# 支持一維多維和交錯數組(數組的數組)

  例子
復制內容到剪貼板
代碼:
int[] array = new int[]; // int 型一維數組
for (int i = ; i < arrayLength; i++)
    array = i;

  int[] array = new int[]; // int 型二維數組
array[] = ;

  int[] array = new int[]; // int 型三維數組
array[] = ;

  int[][] arrayOfarray = new int[]; // int 型交錯數組 數組的數組
arrayOfarray[] = new int[];
arrayOfarray[] = new int[] {};

  索引器

  索引器用於書寫一個可以通過使用 [] 像數組一樣直接訪問集合元素的方法你所需要的只是指定待訪問實例或元素的索引索引器的語法和類屬性語法相同除了接受作為元素索引的輸入參數外

  例子

  注意CollectionBase 是用於建立集合的庫類List 是 CollectionBase 中用於存放集合列表的受保護成員
復制內容到剪貼板
代碼:
class Shapes: CollectionBase
{
    public void add(Shape shp)
    {
        ListAdd(shp);
    }

  //indexer
    public Shape this[int index]
    {
        get {
            return (Shape) List[index];
        }
        set {
            List[index] = value ;
        }
    }
}
裝箱/拆箱

  裝箱的思想在 C# 中是創新的正如前面提到的所有的數據類型無論是內建的還是用戶定義的都是從 System 命名空間的基類 object 繼承的所以基礎的或是原始的類型打包為一個對象稱為裝箱相反的處理稱為拆箱

  例子
復制內容到剪貼板
代碼:
class Test
{
  static void Main()
  {
      int myInt = ;
      object obj = myInt ;      // 裝箱
      int myInt = (int) obj;  // 拆箱
  }
}
例程展示了裝箱和拆箱兩個過程一個 int 值可以被轉換為對象並且能夠再次轉換回 int當某種值類型的變量需要被轉換為一個引用類型時便會產生一個對象箱保存該值拆箱則完全相反當某個對象箱被轉換回其原值類型時該值從箱中拷貝至適當的存儲空間

  函數參數
C# 中的參數有三種類型

      按值傳遞/輸入參數
    按引用傳遞/輸入輸出參數
    輸出參數

  如果你有 COM 接口的思想而且還是參數類型的你會很容易理解 C# 的參數類型

  按值傳遞/輸入參數
值參數的概念和 C++ 中一樣傳遞的值復制到了新的地方並傳遞給函數

  例子
復制內容到剪貼板
代碼:
SetDay();

void SetDay(int day)
{
   
}
按引用傳遞/輸入輸出參數

  C++ 中的引用參數是通過指針或引用運算符 & 傳遞的C# 中的引用參數更不易出錯你可以傳遞一個引用地址你傳遞一個輸入的值並通過函數得到一個輸出的值因此引用參數也被稱為輸入輸出參數

  你不能將未初始化的引用參數傳遞給函數C# 使用關鍵字 ref 指定引用參數你同時還必須在傳遞參數給要求引用參數的函數時使用關鍵字 ref

  例子
復制內容到剪貼板
代碼:
int a= ;
FunctionA(ref a); // 使用 ref否則將引發編譯時錯誤
ConsoleWriteLine(a); // 打印
復制內容到剪貼板
代碼:
void FunctionA(ref int Val)
{
    int x= Val;
    Val = x* ;   
}
輸出參數

  輸出參數是只從函數返回值的參數輸入值不要求C# 使用關鍵字 out 表示輸出參數

  例子
復制內容到剪貼板
代碼:
int Val;
    GetNodeValue(Val);
復制內容到剪貼板
代碼:
bool GetNodeValue(out int Val)
    {
        Val = value;
        return true;
    }
參數和數組的數量變化

  C# 中的數組使用關鍵字 params 進行傳遞一個數組類型的參數必須總是函數最右邊的參數只有一個參數可以是數組類型你可以傳送任意數量的元素作為數組類型的參數看了下面的例子你可以更好的理解

  注意使用數組是 C# 提供用於可選或可變數量參數的唯一途徑

  例子
復制內容到剪貼板
代碼:
void Func(params int[] array)
    {
        ConsoleWriteLine(number of elements {} arrayLength);
    }
復制內容到剪貼板
代碼:
Func(); // 打印
    Func(); // 打印
    Func(); // 打印
    Func(new int[] {}); // 打印
    int[] array = new int[] {};
    Func(array); // 打印
運算符與表達式

  運算符和表達式跟 C++ 中完全一致然而同時也添加了一些新的有用的運算符有些在這裡進行了討論

  is 運算符

  is 運算符是用於檢查操作數類型是否相等或可以轉換is 運算符特別適合用於多態的情形is 運算符使用兩個操作數其結果是布爾值參考例子
復制內容到剪貼板
代碼:
void function(object param)
{
    if(param is ClassA)
        //做要做的事
    else if(param is MyStruct)
        //做要做的事       
    }
}
as 運算符

  as 運算符檢查操作數的類型是否可轉換或是相等(as 是由 is 運算符完成的)如果是則處理結果是已轉換或已裝箱的對象(如果操作數可以裝箱為目標類型參考 裝箱/拆箱)如果對象不是可轉換的或可裝箱的返回值為 null看看下面的例子以更好的理解這個概念
復制內容到剪貼板
代碼:
Shape shp = new Shape();
Vehicle veh = shp as Vehicle; // 返回 null類型不可轉換

  Circle cir = new Circle();
Shape shp = cir;
Circle cir = shp as Circle;  //將進行轉換

  object[] objects = new object[];
objects[] = Aisha;
object[] = new Shape();

  string str;
for(int i=; i&< objectsLength; i++)
{
    str = objects as string;
    if(str == null)
        ConsoleWriteLine(can not be converted);
    else
        ConsoleWriteLine({}str);
}
復制內容到剪貼板
代碼:
Output:
Aisha
can not be converted
語句

  除了些許附加的新語句和修改外C# 的語句和 C++ 的基本一致

  以下是新的語句

  foreach

  用於迭代數組等集合

  例子
復制內容到剪貼板
代碼:
foreach (string s in array)
        ConsoleWriteLine(s);
lock

  在線程中使代碼塊稱為重點部分
(譯注lock 關鍵字將語句塊標記為臨界區方法是獲取給定對象的互斥鎖執行語句然後釋放該鎖lock 確保當一個線程位於代碼的臨界區時另一個線程不進入臨界區如果其他線程試圖進入鎖定的代碼則它將一直等待(即被阻止)直到該對象被釋放

  checked/unchecked

  用於數字操作中的溢出檢查

  例子
復制內容到剪貼板

  代碼:
int x = IntMaxValue; x++; // 溢出檢查
{
x++; // 異常
}
unchecked
{
x++; // 溢出
}
下面的語句已修改(譯注原文如此疑為作者筆誤)
Switch

  Switch 語句在 C# 中修改過

  現在在執行一條 case 語句後程序流不能跳至下一 case 語句之前在 C++ 中這是可以的

  例子
復制內容到剪貼板
代碼:
 int var = ;
switch (var)
{
    case : ConsoleWriteLine(<Value is >); // 這裡沒有 break
    case : ConsoleWriteLine(<Value is >); break;
}
C++ 的輸出
復制內容到剪貼板
代碼:
<Value is ><Value is >
而在 C# 中你將得到一個編譯時錯誤
復制內容到剪貼板
代碼:
 error CS: Control cannot fall through
      from one case label (case :) to another
然而你可以像在 C++ 中一樣這麼用
復制內容到剪貼板
代碼:
 switch (var)
{
    case :
    case : ConsoleWriteLine( or <VALUE is >); break;
}
你還可以用常數變量作為 case 值

  例子
復制內容到剪貼板
代碼:
 const string WeekEnd = Sunday;
const string WeekDay = Monday;

  

  string WeekDay = ConsoleReadLine();
switch (WeekDay )
{
case WeekEnd: ConsoleWriteLine(Its weekend!!); break;
case WeekDay: ConsoleWriteLine(Its Monday); break;

  }


委托

  委托讓我們可以把函數引用保存在變量中這就像在 C++ 中使用 typedef 保存函數指針一樣

  委托使用關鍵字 delegate 聲明看看這個例子你就能理解什麼是委托

  例子
復制內容到剪貼板
代碼:
 delegate int Operation(int val int val);
public int Add(int val int val)
{
    return val + val;
}
public int Subtract (int val int val)
{
    return val val;
}

  public void Perform()
{
    Operation Oper;
    ConsoleWriteLine(Enter + or );
    string optor = ConsoleReadLine();
    ConsoleWriteLine(Enter operands);
           
    string opnd = ConsoleReadLine();
    string opnd = ConsoleReadLine();
           
    int val = ConvertToInt (opnd);           
    int val = ConvertToInt (opnd);
           
    if (optor == +)
        Oper = new Operation(Add);
    else
        Oper = new Operation(Subtract);
       
    ConsoleWriteLine( Result = {} Oper(val val));
}


繼承與多態

  C# 只允許單一繼承多重繼承可以通過接口達到

  例子
復制內容到剪貼板
代碼:
class Parent{
}

  class Child : Parent
虛函數

  虛函數在 C# 中同樣是用於實現多態的概念的除了你要使用 override 關鍵字在子類中實現虛函數外父類使用同樣的 virtual 關鍵字每個重寫虛函數的類都使用 override 關鍵字(譯注作者所說的同樣除……外都是針對 C# 和 C++ 而言的)
復制內容到剪貼板
代碼:
 class Shape
{
    public virtual void Draw()
    {
        ConsoleWriteLine(ShapeDraw)    ;
    }
}

  class Rectangle : Shape

  {
    public override void Draw()
    {
        ConsoleWriteLine(RectangleDraw);
    }           
}

  class Square : Rectangle
{
    public override void Draw()
    {
        ConsoleWriteLine(SquareDraw);
    }
}
class MainClass
{
    static void Main(string[] args)
    {
        Shape[] shp = new Shape[];
        Rectangle rect = new Rectangle();
       
        shp[] = new Shape();
        shp[] = rect;
        shp[] = new Square();
                   
        shp[]Draw();
        shp[]Draw();
        shp[]Draw();
    }
}
Output:
ShapeDraw
RectangleDraw
SquareDraw


使用new隱藏父類函數

  你可以隱藏基類中的函數而在子類中定義其新版本關鍵字 new 用於聲明新的版本思考下面的例子該例是上一例子的修改版本注意輸出我用 關鍵字 new 替換了 Rectangle 類中的關鍵字 override
復制內容到剪貼板
代碼:
 class Shape
{
    public virtual void Draw()
    {
        ConsoleWriteLine(ShapeDraw)    ;
    }
}

  class Rectangle : Shape
{
    public new void Draw()
    {
        ConsoleWriteLine(RectangleDraw);
    }           
}
class Square : Rectangle
{
    //這裡不用 override
    public new void Draw()
    {
        ConsoleWriteLine(SquareDraw);
    }
}
class MainClass
{
    static void Main(string[] args)
    {
        ConsoleWriteLine(Using Polymorphism:);
        Shape[] shp = new Shape[];
        Rectangle rect = new Rectangle();
           
        shp[] = new Shape();
        shp[] = rect;
        shp[] = new Square();
                       
        shp[]Draw();
        shp[]Draw();
        shp[]Draw();
           
        ConsoleWriteLine(Using without Polymorphism:);
        rectDraw();           
        Square sqr = new Square();
        sqrDraw();
    }
}   
   
Output:
Using Polymorphism
ShapeDraw
ShapeDraw
ShapeDraw
Using without Polymorphism:
RectangleDraw
SquareDraw


多態性認為 Rectangle 類的 Draw 方法是和 Shape 類的 Draw 方法不同的另一個方法而不是認為是其多態實現所以為了防止父類和子類間的命名沖突我們只有使用 new 修飾符

  注意你不能在一個類中使用一個方法的兩個版本一個用 new 修飾符另一個用 override 或 virtual就像在上面的例子中我不能在 Rectangle 類中增加另一個名為 Draw 的方法因為它是一個 virtual 或 override 的方法同樣在 Square 類中我也不能重寫 Shape 類的虛方法 Draw

  調用基類成員

  如果子類的數據成員和基類中的有同樣的名字為了避免命名沖突基類成員和函數使用 base 關鍵字進行訪問看看下面的例子基類構造函數是如何調用的而數據成員又是如何使用的
復制內容到剪貼板
代碼:
 public Child(int val) :base(val)
{
    myVar = ;
    basemyVar;
}

  OR

  public Child(int val)
{
    base(val);
    myVar = ;
    basemyVar;
}


前景展望

  本文僅僅是作為 C# 語言的一個快速浏覽以便你可以熟悉該語言的一些特性盡管我嘗試用實例以一種簡短而全面的方式討論了 C# 幾乎所有的主要概念但我認為還是有很多內容需要增加和討論的
 
  以後我會增加更多的沒有討論過的命令和概念包括事件等我還想給初學者寫一下怎麼用 C# 進行 Windows 編程


From:http://tw.wingwit.com/Article/program/net/201311/13663.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.