最簡單的C#快速入門教程
在一小時(shí)內(nèi)學(xué)會(huì) C#。使用例程,簡單卻完整的探索 C# 語言的構(gòu)造和特點(diǎn)。本文特別適合有 C++ 基礎(chǔ)卻沒有太多精力學(xué)習(xí) C# 的讀者。
簡介
C# 是一種具有 C++ 特性,Java 樣式及 BASIC 快速建模特性的編程語言。如果你已經(jīng)知曉 C++ 語言,本文將在不到一小時(shí)的時(shí)間內(nèi)帶你快速瀏覽 C# 的語法。如果熟悉 Java 語言,Java 的編程結(jié)構(gòu)、打包和垃圾回收的概念肯定對(duì)你快速學(xué)習(xí) C# 大有幫助。所以我在討論 C# 語言構(gòu)造的時(shí)候會(huì)假設(shè)你知道 C++。
本文通過一系列例程以簡短但全面的方式討論了 C# 語言構(gòu)造和特性,所以你僅需略覽代碼片刻,即可了解其概念。
注意:本文不是為 C# 宗師而寫。有很多初學(xué)者的 C# 文章,這只是其中之一。
接下來關(guān)于 C# 的討論主題:
編程結(jié)構(gòu)
命名空間
數(shù)據(jù)類型
變量
運(yùn)算符與表達(dá)式
枚舉
語句
類與結(jié)構(gòu)
修飾符
屬性
接口
函數(shù)參數(shù)
數(shù)組
索引器
裝箱與拆箱
委托
繼承與多態(tài)
以下主題不會(huì)進(jìn)行討論:
C++ 與 C# 的共同點(diǎn)
諸如垃圾回收、線程、文件處理等概念
數(shù)據(jù)類型轉(zhuǎn)換
異常處理
.NET 庫
編程結(jié)構(gòu)
和 C++ 一樣,C# 是大小寫敏感的。半角分號(hào)(;)是語句分隔符。和 C++ 有所區(qū)別的是,C# 中沒有單獨(dú)的聲明(頭)和實(shí)現(xiàn)(CPP)文件。所有代碼(類聲明和實(shí)現(xiàn))都放在擴(kuò)展名為 cs 的單一文件中。
看看 C# 中的 Hello World 程序。
代碼:
using System;
namespace MyNameSpace
{
class HelloWorld
{
static void Main(string[] args)
{
Console.WriteLine ("Hello World");
}
}
}
C# 中所有內(nèi)容都打包在類中,而所有的類又打包在命名空間中(正如文件存與文件夾中)。和 C++ 一樣,有一個(gè)主函數(shù)作為你程序的入口點(diǎn)。C++ 的主函數(shù)名為 main,而 C# 中是大寫 M 打頭的 Main。
類塊或結(jié)構(gòu)定義之后沒有必要再加一個(gè)半角分號(hào)。C++ 中是這樣,但 C# 不要求。
命名空間
每個(gè)類都打包于一個(gè)命名空間。命名空間的概念和 C++ 完全一樣,但我們?cè)?C# 中比在 C++ 中更加頻繁的使用命名空間。你可以用點(diǎn)(.)定界符訪問命名空間中的類。上面的 Hello World 程序中,MyNameSpace 是其命名空間。
現(xiàn)在思考當(dāng)你要從其他命名空間的類中訪問 HelloWorld 類。
代碼:
using System;
namespace AnotherNameSpace
{
class AnotherClass
{
public void Func()
{
Console.WriteLine ("Hello World");
}
}
}
現(xiàn)在在你的 HelloWorld 類中你可以這樣訪問:
代碼:
using System;
using AnotherNameSpace; // 你可以增加這條語句
namespace MyNameSpace
{
class HelloWorld
{
static void Main(string[] args)
{
AnotherClass obj = new AnotherClass();
obj.Func();
}
}
}
在 .NET 庫中,System 是包含其他命名空間的頂層命名空間。默認(rèn)情況下存在一個(gè)全局命名空間,所以在命名空間外定義的類直接進(jìn)到此全局命名空間中,因而你可以不用定界符訪問此類。
你同樣可以定義嵌套命名空間。
Using
#include 指示符被后跟命名空間名的 using 關(guān)鍵字代替了。正如上面的 using System。System 是最基層的命名空間,所有其他命名空間和類都包含于其中。System 命名空間中所有對(duì)象的基類是 Object。
變量
除了以下差異,C# 中的變量幾乎和 C++ 中一樣:
1. C# 中(不同于 C++)的變量,總是需要你在訪問它們前先進(jìn)行初始化,否則你將遇到編譯時(shí)錯(cuò)誤。故而,不可能訪問未初始化的變量。
2. 你不能在 C# 中訪問一個(gè)“掛起”指針。
3. 超出數(shù)組邊界的表達(dá)式索引值同樣不可訪問。
4. C# 中沒有全局變量或全局函數(shù),取而代之的是通過靜態(tài)函數(shù)和靜態(tài)變量完成的。
數(shù)據(jù)類型
所有 C# 的類型都是從 object 類繼承的。有兩種數(shù)據(jù)類型:
1. 基本/內(nèi)建類型
2. 用戶定義類型
以下是 C# 內(nèi)建類型的列表:
類型 字節(jié) 描述
byte 1 unsigned byte
sbyte 1 signed byte
short 2 signed short
ushort 2 unsigned short
int 4 signed integer
uint 4 unsigned integer
long 8 signed long
ulong 8 unsigned long
float 4 floating point number
double 8 double precision number
decimal 8 fixed precision number
string - Unicode string
char - Unicode char
bool true, false boolean
注意:C# 的類型范圍和 C++ 不同。例如:long 在 C++ 中是 4 字節(jié)而在 C# 中是 8 字節(jié)。bool 和 string 類型均和 C++ 不同。bool 僅接受真、假而非任意整數(shù)。
用戶定義類型文件包含:
1. 類 (class)
2. 結(jié)構(gòu)(struct)
3. 接口(interface)
以下類型繼承時(shí)均分配內(nèi)存:
1. 值類型
2. 參考類型
值類型
值類型是在堆棧中分配的數(shù)據(jù)類型。它們包括了:
除字符串,所有基本和內(nèi)建類型
結(jié)構(gòu)
枚舉類型
引用類型
引用類型在堆(heap)中分配內(nèi)存且當(dāng)其不再使用時(shí),將自動(dòng)進(jìn)行垃圾清理。和 C++ 要求用戶顯示創(chuàng)建 delete 運(yùn)算符不一樣,它們使用新運(yùn)算符創(chuàng)建,且沒有 delete 運(yùn)算符。在 C# 中它們自動(dòng)由垃圾回收系統(tǒng)回收。
引用類型包括:
類
接口
集合類型如數(shù)組
字符串
枚舉
C# 中的枚舉和 C++ 完全一樣。通過關(guān)鍵字 enum 定義。
例子:
代碼:
enum Weekdays
{
Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday
}
類與結(jié)構(gòu)
除了內(nèi)存分配的不同外,類和結(jié)構(gòu)就和 C++ 中的情況一樣。類的對(duì)象在堆中分配,并使用 new 關(guān)鍵字創(chuàng)建。而結(jié)構(gòu)是在棧(stack)中進(jìn)行分配。C# 中的結(jié)構(gòu)屬于輕量級(jí)快速數(shù)據(jù)類型。當(dāng)需要大型數(shù)據(jù)類型時(shí),你應(yīng)該創(chuàng)建類。
例子:
代碼:
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/4 == 0);
}
public void SetDate (int day, int month, int year)
{
}
...
}
屬性
如果你熟悉 C++ 面向?qū)ο蟮姆椒ǎ阋欢▽?duì)屬性有自己的認(rèn)識(shí)。對(duì) C++ 來說,前面例子中 Date 類的屬性就是 day、month 和 year,而你添加了 Get 和 Set 方法。C# 提供了一種更加便捷、簡單而又直接的屬性訪問方式。
所以上面的類應(yīng)該寫成這樣:
代碼:
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%4== 0 ? true: false;
}
public void SetDate (int day, int month, int year)
{
this.day = day;
this.month = month;
this.year = year;
}
}
這里是你 get 和 set 屬性的方法:
代碼:
class User
{
public static void Main()
{
Date date = new Date();
date.Day = 27;
date.Month = 6;
date.Year = 2003;
Console.WriteLine
("Date: {0}/{1}/{2}", date.Day, date.Month, date.Year);
}
}
修飾符
你必須知道 C++ 中常用的 public、private 和 protected 修飾符。我將在這里討論一些 C# 引入的新的修飾符。
readonly
readonly 修飾符僅用于修飾類的數(shù)據(jù)成員。正如其名字說的,一旦它們已經(jīng)進(jìn)行了寫操作、直接初始化或在構(gòu)造函數(shù)中對(duì)其進(jìn)行了賦值,readonly 數(shù)據(jù)成員就只能對(duì)其進(jìn)行讀取。readonly 和 const 數(shù)據(jù)成員不同之處在于 const 要求你在聲明時(shí)進(jìn)行直接初始化。看下面的例程:
代碼:
class MyClass
{
const int constInt = 100; //直接進(jìn)行
readonly int myInt = 5; //直接進(jìn)行
readonly int myInt2;
public MyClass()
{
myInt2 = 8; //間接進(jìn)行
}
public Func()
{
myInt = 7; //非法
Console.WriteLine(myInt2.ToString());
}
}
sealed
帶有 sealed 修飾符的類不允許你從它繼承任何類。所以如果你不想一個(gè)類被繼承,你可以對(duì)該類使用 sealed 關(guān)鍵字。
代碼:
sealed class CanNotbeTheParent
{
int a = 5;
}
unsafe
你可以使用 unsafe 修飾符在 C# 中定義一個(gè)不安全上下文。在不安全上下文中,你可以插入不安全代碼,如 C++ 的指針等。參見以下代碼:
代碼:
public unsafe MyFunction( int * pInt, double* pDouble)
{
int* pAnotherInt = new int;
*pAnotherInt = 10;
pInt = pAnotherInt;
...
*pDouble = 8.9;
}
接口
如果你有 COM 的思想,你馬上就知道我在說什么了。接口是只包含函數(shù)簽名而在子類中實(shí)現(xiàn)的抽象基類。在 C# 中,你可以用 interface 關(guān)鍵字聲明這樣的接口類。.NET 就是基于這樣的接口的。C# 中你不能對(duì)類進(jìn)行多重繼承——這在 C++ 中是允許的。通過接口,多重繼承的精髓得以實(shí)現(xiàn)。即你的子類可以實(shí)現(xiàn)多重接口。(譯注:由此可以實(shí)現(xiàn)多重繼承)
代碼:
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)
{
.....
}
}
數(shù)組
數(shù)組在 C# 中比 C++ 中要高級(jí)很多。數(shù)組分配于堆中,所以是引用類型的。你不能訪問數(shù)組邊界外的元素。所以 C# 防止你引發(fā)那種 bug。同時(shí)也提供了迭代數(shù)組元素的幫助函數(shù)。foreach 是這樣的迭代語句之一。C++ 和 C# 數(shù)組的語法差異在于:
方括號(hào)在類型后面而不是在變量名后面
創(chuàng)建元素使用 new 運(yùn)算符
C# 支持一維、多維和交錯(cuò)數(shù)組(數(shù)組的數(shù)組)
例子:
代碼:
int[] array = new int[10]; // int 型一維數(shù)組
for (int i = 0; i < array.Length; i++)
array = i;
int[,] array2 = new int[5,10]; // int 型二維數(shù)組
array2[1,2] = 5;
int[,,] array3 = new int[5,10,5]; // int 型三維數(shù)組
array3[0,2,4] = 9;
int[][] arrayOfarray = new int[2]; // int 型交錯(cuò)數(shù)組 - 數(shù)組的數(shù)組
arrayOfarray[0] = new int[4];
arrayOfarray[0] = new int[] {1,2,15};
索引器
索引器用于書寫一個(gè)可以通過使用 [] 像數(shù)組一樣直接訪問集合元素的方法。你所需要的只是指定待訪問實(shí)例或元素的索引。索引器的語法和類屬性語法相同,除了接受作為元素索引的輸入?yún)?shù)外。
例子:
注意:CollectionBase 是用于建立集合的庫類。List 是 CollectionBase 中用于存放集合列表的受保護(hù)成員。
代碼:
class Shapes: CollectionBase
{
public void add(Shape shp)
{
List.Add(shp);
}
//indexer
public Shape this[int index]
{
get {
return (Shape) List[index];
}
set {
List[index] = value ;
}
}
}
裝箱/拆箱
裝箱的思想在 C# 中是創(chuàng)新的。正如前面提到的,所有的數(shù)據(jù)類型,無論是內(nèi)建的還是用戶定義的,都是從 System 命名空間的基類 object 繼承的。所以基礎(chǔ)的或是原始的類型打包為一個(gè)對(duì)象稱為裝箱,相反的處理稱為拆箱。
例子:
代碼:
class Test
{
static void Main()
{
int myInt = 12;
object obj = myInt ; // 裝箱
int myInt2 = (int) obj; // 拆箱
}
}
例程展示了裝箱和拆箱兩個(gè)過程。一個(gè) int 值可以被轉(zhuǎn)換為對(duì)象,并且能夠再次轉(zhuǎn)換回 int。當(dāng)某種值類型的變量需要被轉(zhuǎn)換為一個(gè)引用類型時(shí),便會(huì)產(chǎn)生一個(gè)對(duì)象箱保存該值。拆箱則完全相反。當(dāng)某個(gè)對(duì)象箱被轉(zhuǎn)換回其原值類型時(shí),該值從箱中拷貝至適當(dāng)?shù)拇鎯?chǔ)空間。
函數(shù)參數(shù)
C# 中的參數(shù)有三種類型:
1. 按值傳遞/輸入?yún)?shù)
2. 按引用傳遞/輸入-輸出參數(shù)
3. 輸出參數(shù)
如果你有 COM 接口的思想,而且還是參數(shù)類型的,你會(huì)很容易理解 C# 的參數(shù)類型。
按值傳遞/輸入?yún)?shù)
值參數(shù)的概念和 C++ 中一樣。傳遞的值復(fù)制到了新的地方并傳遞給函數(shù)。
例子:
代碼:
SetDay(5);
...
void SetDay(int day)
{
....
}
按引用傳遞/輸入-輸出參數(shù)
C++ 中的引用參數(shù)是通過指針或引用運(yùn)算符 & 傳遞的。C# 中的引用參數(shù)更不易出錯(cuò)。你可以傳遞一個(gè)引用地址,你傳遞一個(gè)輸入的值并通過函數(shù)得到一個(gè)輸出的值。因此引用參數(shù)也被稱為輸入-輸出參數(shù)。
你不能將未初始化的引用參數(shù)傳遞給函數(shù)。C# 使用關(guān)鍵字 ref 指定引用參數(shù)。你同時(shí)還必須在傳遞參數(shù)給要求引用參數(shù)的函數(shù)時(shí)使用關(guān)鍵字 ref。
例子:
代碼:
int a= 5;
FunctionA(ref a); // 使用 ref,否則將引發(fā)編譯時(shí)錯(cuò)誤
Console.WriteLine(a); // 打印 20
復(fù)制內(nèi)容到剪貼板
代碼:
void FunctionA(ref int Val)
{
int x= Val;
Val = x* 4;
}
輸出參數(shù)
輸出參數(shù)是只從函數(shù)返回值的參數(shù)。輸入值不要求。C# 使用關(guān)鍵字 out 表示輸出參數(shù)。
例子:
代碼:
int Val;
GetNodeValue(Val);
復(fù)制內(nèi)容到剪貼板
代碼:
bool GetNodeValue(out int Val)
{
Val = value;
return true;
}
參數(shù)和數(shù)組的數(shù)量變化
C# 中的數(shù)組使用關(guān)鍵字 params 進(jìn)行傳遞。一個(gè)數(shù)組類型的參數(shù)必須總是函數(shù)最右邊的參數(shù)。只有一個(gè)參數(shù)可以是數(shù)組類型。你可以傳送任意數(shù)量的元素作為數(shù)組類型的參數(shù)??戳讼旅娴睦幽憧梢愿玫睦斫猓?
注意:使用數(shù)組是 C# 提供用于可選或可變數(shù)量參數(shù)的唯一途徑。
例子:
代碼:
void Func(params int[] array)
{
Console.WriteLine("number of elements {0}", array.Length);
}
代碼:
Func(); // 打印 0
Func(5); // 打印 1
Func(7,9); // 打印 2
Func(new int[] {3,8,10}); // 打印 3
int[] array = new int[8] {1,3,4,5,5,6,7,5};
Func(array); // 打印 8
運(yùn)算符與表達(dá)式
運(yùn)算符和表達(dá)式跟 C++ 中完全一致。然而同時(shí)也添加了一些新的有用的運(yùn)算符。有些在這里進(jìn)行了討論。
is 運(yùn)算符
is 運(yùn)算符是用于檢查操作數(shù)類型是否相等或可以轉(zhuǎn)換。is 運(yùn)算符特別適合用于多態(tài)的情形。is 運(yùn)算符使用兩個(gè)操作數(shù),其結(jié)果是布爾值。參考例子:
代碼:
void function(object param)
{
if(param is ClassA)
//做要做的事
else if(param is MyStruct)
//做要做的事
}
}
as 運(yùn)算符
as 運(yùn)算符檢查操作數(shù)的類型是否可轉(zhuǎn)換或是相等(as 是由 is 運(yùn)算符完成的),如果是,則處理結(jié)果是已轉(zhuǎn)換或已裝箱的對(duì)象(如果操作數(shù)可以裝箱為目標(biāo)類型,參考 裝箱/拆箱)。如果對(duì)象不是可轉(zhuǎn)換的或可裝箱的,返回值為 null。看看下面的例子以更好的理解這個(gè)概念。
代碼:
Shape shp = new Shape();
Vehicle veh = shp as Vehicle; // 返回 null,類型不可轉(zhuǎn)換
Circle cir = new Circle();
Shape shp = cir;
Circle cir2 = shp as Circle; //將進(jìn)行轉(zhuǎn)換
object[] objects = new object[2];
objects[0] = "Aisha";
object[1] = new Shape();
string str;
for(int i=0; i&< objects.Length; i++)
{
str = objects as string;
if(str == null)
Console.WriteLine("can not be converted");
else
Console.WriteLine("{0}",str);
}
代碼:
Output:
Aisha
can not be converted
語句
除了些許附加的新語句和修改外,C# 的語句和 C++ 的基本一致。
以下是新的語句:
foreach
用于迭代數(shù)組等集合。
例子:
代碼:
foreach (string s in array)
Console.WriteLine(s);
lock
在線程中使代碼塊稱為重點(diǎn)部分。
(譯注:lock 關(guān)鍵字將語句塊標(biāo)記為臨界區(qū),方法是獲取給定對(duì)象的互斥鎖,執(zhí)行語句,然后釋放該鎖。lock 確保當(dāng)一個(gè)線程位于代碼的臨界區(qū)時(shí),另一個(gè)線程不進(jìn)入臨界區(qū)。如果其他線程試圖進(jìn)入鎖定的代碼,則它將一直等待(即被阻止),直到該對(duì)象被釋放。)
checked/unchecked
用于數(shù)字操作中的溢出檢查。
例子:
代碼:
int x = Int32.MaxValue; x++; // 溢出檢查
{
x++; // 異常
}
unchecked
{
x++; // 溢出
}
下面的語句已修改:(譯注:原文如此,疑為作者筆誤)
Switch
Switch 語句在 C# 中修改過。
1.現(xiàn)在在執(zhí)行一條 case 語句后,程序流不能跳至下一 case 語句。之前在 C++ 中這是可以的。
例子:
代碼:
int var = 100;
switch (var)
{
case 100: Console.WriteLine("<Value is 100>"); // 這里沒有 break
case 200: Console.WriteLine("<Value is 200>"); break;
}
C++ 的輸出:
代碼:
<Value is 100><Value is 200>
而在 C# 中你將得到一個(gè)編譯時(shí)錯(cuò)誤:
復(fù)制內(nèi)容到剪貼板
代碼:
error CS0163: Control cannot fall through
from one case label ('case 100:') to another
2.然而你可以像在 C++ 中一樣這么用:
代碼:
switch (var)
{
case 100:
case 200: Console.WriteLine("100 or 200<VALUE is 200>"); break;
}
3.你還可以用常數(shù)變量作為 case 值:
例子:
代碼:
const string WeekEnd = "Sunday";
const string WeekDay1 = "Monday";
....
string WeekDay = Console.ReadLine();
switch (WeekDay )
{
case WeekEnd: Console.WriteLine("It's weekend!!"); break;
case WeekDay1: Console.WriteLine("It's Monday"); break;
}
委托
委托讓我們可以把函數(shù)引用保存在變量中。這就像在 C++ 中使用 typedef 保存函數(shù)指針一樣。
委托使用關(guān)鍵字 delegate 聲明??纯催@個(gè)例子,你就能理解什么是委托:
例子:
代碼:
delegate int Operation(int val1, int val2);
public int Add(int val1, int val2)
{
return val1 + val2;
}
public int Subtract (int val1, int val2)
{
return val1- val2;
}
public void Perform()
{
Operation Oper;
Console.WriteLine("Enter + or - ");
string optor = Console.ReadLine();
Console.WriteLine("Enter 2 operands");
string opnd1 = Console.ReadLine();
string opnd2 = Console.ReadLine();
int val1 = Convert.ToInt32 (opnd1);
int val2 = Convert.ToInt32 (opnd2);
if (optor == "+")
Oper = new Operation(Add);
else
Oper = new Operation(Subtract);
Console.WriteLine(" Result = {0}", Oper(val1, val2));
}
繼承與多態(tài)
C# 只允許單一繼承。多重繼承可以通過接口達(dá)到。
例子:
代碼:
class Parent{
}
class Child : Parent
虛函數(shù)
虛函數(shù)在 C# 中同樣是用于實(shí)現(xiàn)多態(tài)的概念的,除了你要使用 override 關(guān)鍵字在子類中實(shí)現(xiàn)虛函數(shù)外。父類使用同樣的 virtual 關(guān)鍵字。每個(gè)重寫虛函數(shù)的類都使用 override 關(guān)鍵字。(譯注:作者所說的“同樣”,“除……外”都是針對(duì) C# 和 C++ 而言的)
代碼:
class Shape
{
public virtual void Draw()
{
Console.WriteLine("Shape.Draw") ;
}
}
class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Rectangle.Draw");
}
}
class Square : Rectangle
{
public override void Draw()
{
Console.WriteLine("Square.Draw");
}
}
class MainClass
{
static void Main(string[] args)
{
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
}
}
Output:
Shape.Draw
Rectangle.Draw
Square.Draw
使用“new”隱藏父類函數(shù)
你可以隱藏基類中的函數(shù)而在子類中定義其新版本。關(guān)鍵字 new 用于聲明新的版本。思考下面的例子,該例是上一例子的修改版本。注意輸出,我用 關(guān)鍵字 new 替換了 Rectangle 類中的關(guān)鍵字 override。
代碼:
class Shape
{
public virtual void Draw()
{
Console.WriteLine("Shape.Draw") ;
}
}
class Rectangle : Shape
{
public new void Draw()
{
Console.WriteLine("Rectangle.Draw");
}
}
class Square : Rectangle
{
//這里不用 override
public new void Draw()
{
Console.WriteLine("Square.Draw");
}
}
class MainClass
{
static void Main(string[] args)
{
Console.WriteLine("Using Polymorphism:");
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
Console.WriteLine("Using without Polymorphism:");
rect.Draw();
Square sqr = new Square();
sqr.Draw();
}
}
Output:
Using Polymorphism
Shape.Draw
Shape.Draw
Shape.Draw
Using without Polymorphism:
Rectangle.Draw
Square.Draw
多態(tài)性認(rèn)為 Rectangle 類的 Draw 方法是和 Shape 類的 Draw 方法不同的另一個(gè)方法,而不是認(rèn)為是其多態(tài)實(shí)現(xiàn)。所以為了防止父類和子類間的命名沖突,我們只有使用 new 修飾符。
注意:你不能在一個(gè)類中使用一個(gè)方法的兩個(gè)版本,一個(gè)用 new 修飾符,另一個(gè)用 override 或 virtual。就像在上面的例子中,我不能在 Rectangle 類中增加另一個(gè)名為 Draw 的方法,因?yàn)樗且粋€(gè) virtual 或 override 的方法。同樣在 Square 類中,我也不能重寫 Shape 類的虛方法 Draw。
調(diào)用基類成員
如果子類的數(shù)據(jù)成員和基類中的有同樣的名字,為了避免命名沖突,基類成員和函數(shù)使用 base 關(guān)鍵字進(jìn)行訪問??纯聪旅娴睦?,基類構(gòu)造函數(shù)是如何調(diào)用的,而數(shù)據(jù)成員又是如何使用的。
代碼:
public Child(int val) :base(val)
{
myVar = 5;
base.myVar;
}
OR
public Child(int val)
{
base(val);
myVar = 5 ;
base.myVar;
}
本文僅僅是作為 C# 語言的一個(gè)快速瀏覽,以便你可以熟悉該語言的一些特性。盡管我嘗試用實(shí)例以一種簡短而全面的方式討論了 C# 幾乎所有的主要概念,但我認(rèn)為還是有很多內(nèi)容需要增加和討論的。