引言:每隔10年左右,編程人員就需要花費大量的時間和精力去學習新的編程技術。在80年代是Unix和C,90年代是Windows和C++,現在又輪到了微軟的.NETFramework和C#。盡管需要學習新的技術,但由此帶來的好處卻遠高於付出的勞動。幸運的是,使用C#和.NET進行的大多數工程的分析和設計與在C++和Windows中沒有本質的變化。在本篇文章中,我將介紹如何實現由C++到C#的飛躍。
系列文章:[由C++轉向C#需要注意的變化(一)]
New的調用
在C++中,new關健字可以在堆上生成一個對象。在C#中卻不是這樣。對於引用類型變量而言,new關健字在堆上生成一個對象;對於結構等值類型變量而言,new關健字在棧中生成一個對象,並需要調用constructor。
事實上,我們可以不使用new關健字而在棧上生成一個結構類型的變量,但這時需要注意的是,New關健字能夠初始化對象。如果不使用new,則在使用前必須手工地對結構中的所有成員進行初始化,否則在編譯時會出錯。
對象的初始化
usingSystem;//有二個成員變量和一個構造器的簡單結構
publicstructPoint
{
publicPoint(intx,inty)
{
this.x=x;
this.y=y;
}
publicintx;
publicinty;
}
publicclassTester
{
publicstaticvoidMain()
{
Testert=newTester();
t.Run();
}
publicvoidRun()
{
Pointp1=newPoint(5,12);
SomeMethod(p1);//fine
Pointp2;//不調用new而直接創建
//編譯器編譯到這裡時會出錯,因為p2的成員變量沒有被初始化
//SomeMethod(p2);
//手工對它們進行初始化
p2.x=1;
p2.y=2;
SomeMethod(p2);
}
//一個可以接受Point作為參數的方法
privatevoidSomeMethod(Pointp)
{
Console.WriteLine("Pointat{0}x{1}",
p.x,p.y);
}
}
屬性
大多數的C++編程人員都希望使成員變量的屬性為private,這種隱藏數據的想法促進了數據封裝概念的出現,使我們能夠在不改變用戶依賴的接口的情況下而改變類的實現。通常情況下,我們只希望客戶獲取或設置這些成員變量的值。因此,C++編程人員開發出了用來存取private成員變量的存取器。
在C#中,屬性是類的第一級成員。對於客戶而言,屬性看起來象一個成員變量。對於類的實現者而言,它看起來更象是方法。這種設計很巧妙,既可以實現數據的隱藏和封裝,又可以使客戶很方便地訪問成員變量。
我們可以在Employee類中添加一個Age屬性,使客戶可以很方便地獲取和設置員工年齡這個類的成員:
publicintAge
{
get
{
returnage;
}
set
{
age=value;
}
}
關健字value可以被屬性隱性地使用。如果編寫如下的代碼:
Fred.Age=17;
編譯器將會把值17傳遞給value。
通過只采用Get而不采用Set,我們可以為YearsServed創建一個只讀的屬性:
publicintYearsServed
{
get
{
returnyearsServed;
}
}Accessors的使用
privatevoidRun()
{
EmployeeFred=newEmployee(25,101,7);
Console.WriteLine("Fredsage:{0}",
Fred.Age);
Fred.Age=55;
Console.WriteLine("Fredsage:{0}",
Fred.Age);
Console.WriteLine("Fredsservice:{0}",
Fred.YearsServed);
//Fred.YearsServed=12;//是不被允許的
}
我們可以通過屬性獲取Fred的年齡,也可以使用這一屬性設置年齡。我們雖然可以訪問YearsServed屬性獲得它的值,但不能設置值。如果沒有注釋掉最後一行的代碼,在編譯時就會出錯。
如果以後決定從數據庫中獲取Employee的年齡,我們就只需要改變存取器的實現,而客戶不會受到任何影響。
數組
C#提供了一個數組類,它比C/C++中傳統的數組更智能化。例如,在C#中寫數組時不會超出邊界。此外,數組還有一個更智能的伙伴—ArrayList,可以動態地增長,管理對數組大小不斷變化的需求。
C#中的數組有三種形式:一維數組、多維均勻數組(象C++中傳統的數組那樣)、非均勻數組(數組的數組)。我們可以通過下面的代碼創建一維數組:
int[]myIntArray=newint[5];
另外,還可以以如下的方式對它進行初始化:
int[]myIntArray={2,4,6,8,10};
我們可以通過如下方式創建一個4×3的均勻數組:
int[,]myRectangularArray=newint[rows,columns];
我們可以按如下方式對該數組進行初始化:
int[,]myRectangularArray=
{
{0,1,2},{3,4,5},{6,7,8},{9,10,11}
};
由於非均勻數組是數組的數組,因此,我們只能創建一維非均勻數組:
int[][]myJaggedArray=newint[4][];
然後再創建內部的每個數組:
myJaggedArray[0]=newint[5];
myJaggedArray[1]=newint[2];
myJaggedArray[2]=newint[3];
myJaggedArray[3]=newint[5];
由於數組是由繼承System.Array對象而得到的,因此,它們帶有許多包括Sort、Reverse在內的許多有用的方法。
索引器
我們可以創建象數組一樣的對象。例如,我們可以創建一個顯示一系列字符串的列表框,可以把列表框當作一個數組,使用一個索引就可以很方便地訪問列表框中的內容。
stringtheFirstString=myListBox[0];
stringtheLastString=myListBox[Length-1];
這是通過索引器完成的。索引器在很大程度上象一個屬性,但支持索引操作的語法。圖4顯示了一個後面跟著索引操作符的屬性,圖5顯示如何完成一個很簡單的ListBox類並對它進行索引:
界面
軟件界面是二種對象之間如何進行交互的契約。如果一個對象發布了一個界面,就等於向所有可能的客戶聲明:我支持下面的方法、屬性、事件和索引器。
C#是一種面向對象的語言,因此這些契約被封裝在一個被稱作界面的實體中,界面定義了封裝著契約的引用型類型的對象。從概念上來講,界面與抽象類非常相似,二者的區別是抽象類可以作為一系列衍生類的基礎類,界面則是與其他繼承樹結合在一起的。