微軟推出Visual C# .NET已經(jīng)超過半年,.NET Framework作為下一代的開發(fā)工具,擁有著許多以往的RAD開發(fā)工具不可比擬的優(yōu)勢(shì)。其中最大的兩個(gè)亮點(diǎn)就是強(qiáng)化的IDE和封裝得更加完整且便于使用的System等對(duì)象;這些特性使得微軟可以將面向?qū)ο缶幊痰膬?yōu)勢(shì)表現(xiàn)得淋漓盡致。眾所周知,.NET Framework的特點(diǎn)在于高度集成了諸如COM、移動(dòng)設(shè)備編程功能等,但筆者卻想通過一些普通的Win32應(yīng)用程序開發(fā)過程來比較一下Visual C# .NET和其它RAD的開發(fā)方便程度以及程序健壯性等問題。下面,讓我們一起來通過一個(gè)筆者親寫過實(shí)例來看看使用Visual C# .NET編程的利弊。
編程的任務(wù)是通過深度優(yōu)先遍歷一顆目錄樹,枚舉其中的某種擴(kuò)展名的文件,尋找相應(yīng)的另一種擴(kuò)展名的文件是否存在并輸出不存在相應(yīng)擴(kuò)展名文件的列表。比如ABCD.EXE文件需要一個(gè)ABCD.TXT作為對(duì)應(yīng)文件,若ABCD.TXT不存在,則ABCD.EXE就將被列入輸出的列表。文件的擴(kuò)展名和目錄樹都由用戶給定,并且要求要有一個(gè)比較有親和力的用戶界面。
首先,我們使用傳統(tǒng)的RAD開發(fā)工具——Borland C++ Builder 6來開發(fā)這個(gè)應(yīng)用程序。在編程思路極其簡(jiǎn)單,但在代碼上卻很容易出錯(cuò)。通過筆者的實(shí)踐,發(fā)現(xiàn)使用C++ Builder的VCL提供的FindFirst()、FindNext()和FindClose()函數(shù)在代碼實(shí)現(xiàn)上并不流暢,代碼思想上也難以一下子接受。除了要使用while do循環(huán)外,配合使用的ChDir()函數(shù)也得用上,而且必須有尋找子節(jié)點(diǎn)和父節(jié)點(diǎn)的參數(shù)(幸虧BCB都提供了這些參數(shù))。另外,由于文件和目錄的混排,目錄和文件的區(qū)分判斷也顯得龐大。下面是遞歸函數(shù)的完整代碼:
void SearchDir(String filename){
TSearchRec curfile;
AnsiString filename1;
ChDir(filename);
//ShowMessage(filename);
if (FindFirst(filename+"*.*",faAnyFile,curfile) == 0) {
//ShowMessage("OK");
do
{
if ( (curfile.Attr & faDirectory) && curfile.Name != "." && curfile.Name != ".." ) {
SearchDir(ExpandFileName(curfile.Name)+"\\");
}
else
{
if (DirectoryExists(ExpandFileName(curfile.Name)) == false)
{
filename1 = ExpandFileName(curfile.Name).SubString(0,ExpandFileName(curfile.Name).Length()-frmMain->edtExt1->Text.Length());
//ShowMessage(filename1);
if ( (FileExists(filename1+frmMain->edtExt2->Text) == false) && (FileExists(filename1+frmMain->edtExt1->Text) == true) ) {
frmMain->lstResult->Items->Append(ExpandFileName(curfile.Name));
}
}
}
} while ( FindNext(curfile) == 0 );
FindClose(curfile);
}
ChDir("..");
}
容易引起我們注意的地方包括多次使用的ExpandFileName()函數(shù)以及大量的字符串操作。這都不得不令我們擔(dān)心程序的運(yùn)行效率會(huì)遭受影響。由于多次判斷DirectoryExists()和FileExists(),效率也會(huì)受到影響。從整體上看,這是一個(gè)普遍意義上的枚舉算法,轉(zhuǎn)化為二叉樹后的時(shí)間復(fù)雜度約等于O(2^N)。還有一點(diǎn),就是這個(gè)程序需要用到模操作。
下面我們來看看Visual C# .NET的遞歸函數(shù)。
private void SearchDir(string fsoname)
{
foreach ( string fsoname1 in System.IO.Directory.GetFileSystemEntries(fsoname) )
{
if ( System.IO.Directory.Exists(fsoname1) )
{
SearchDir(fsoname1);
}
else
{
if (fsoname1.ToUpper().EndsWith(edtExt.Text.ToUpper()))
{
string fsoname2 = (fsoname1.Substring(0,fsoname1.Length-edtExt.Text.Length) + edtExt2.Text);
if (System.IO.File.Exists (fsoname2) == false)
{
lstResult.Items.Add(fsoname1);
}
}
}
}
}
看完這個(gè)筆者自己寫的程序后,就連筆者自己也不得不贊嘆程序的簡(jiǎn)單和思路的清晰。整個(gè)程序就像英文短文一樣易于閱讀和理解,而且僅用到了System對(duì)象和簡(jiǎn)單的字符串操作。令人驚喜的是,由于在C#中字符串也是對(duì)象,它的操作非常簡(jiǎn)單,很多函數(shù)已經(jīng)轉(zhuǎn)化為對(duì)象的方法了,比如fsoname1.ToUpper().EndsWith()方法,這樣就可以最大程度避免程序員找函數(shù)參數(shù)括號(hào)之苦了。而在BCB的程序中,我們隨處可見括號(hào)而且十分難于對(duì)應(yīng)。
System對(duì)象在這個(gè)過程中所扮演的角色最令人注目;大約40%的代碼都被它節(jié)省下來了,而且從代碼中我們可以強(qiáng)烈感受到,使用這個(gè)對(duì)象十分的簡(jiǎn)單。
這僅僅是代碼編寫的最終結(jié)果,在編寫過程中,Visual C# .NET的文本編輯器的表現(xiàn)也明顯好于BCB,BCB的上下文提示在一旦出現(xiàn)暫時(shí)性語法錯(cuò)誤時(shí)就會(huì)中止,而且文字的加粗并非十分科學(xué)。而C#的文本編輯器不僅提供了括號(hào)的自動(dòng)瞬間加粗對(duì)應(yīng)功能外,上下文提示和語法檢查也十分完整、迅速。
以上所提及的都是Visual C# .NET的優(yōu)點(diǎn),但是作為一個(gè)新生的RAD開發(fā)工具,C#也有許多不足,最致命的就是軟件的運(yùn)行效率和程序的兼容性。
首先我們來測(cè)試一下上面的程序的效率。乍看起來BCB的程序要比C#復(fù)雜許多,但是程序的運(yùn)行效率卻證明了BCB的編譯器要明顯優(yōu)于.NET Framework的。在P4 1.8GHz/1024MB/Windows XP的環(huán)境下,對(duì)2300個(gè)文件進(jìn)行配對(duì),C++Builder的程序花了不到300毫秒的時(shí)間(包括輸出),而C#的程序算上輸出幾乎花去了2500毫秒。這還不要緊,軟件的啟動(dòng)速度差別也很大,C++Builder的程序啟動(dòng)時(shí)間幾乎可以忽略不計(jì),而C#的程序需要3秒左右才能看到主界面,這或許和C#特有的InitializeComponent()過程有關(guān)吧。
軟件運(yùn)行速度的不理想似乎已經(jīng)是微軟的嗜好了,因?yàn)樗麄兛偲诖柖傻谋幼o(hù)。但是,另一個(gè).NET Framework不可忽視的問題就是,運(yùn)行所有.NET Framework程序都需要.NET Framework的程序再發(fā)行包,而這個(gè)包不隨現(xiàn)在市面上除了Windows Server 2003以外的任何操作系統(tǒng)提供。要是這個(gè)包也和Visual Basic以往的運(yùn)行庫那樣也就罷了,偏偏這個(gè)包天生肥胖,竟有23.2MB。而擁有大量用戶群的Windows 98/ME/2000/XP系統(tǒng)都必須先安裝.NET Framework才能運(yùn)行Visual C# .NET的程序。還有更氣人的,這個(gè)包的安裝需要的先決條件包括了安裝有Internet Explorer 5.01或更高版本和Windows Installer。這些軟件尤其是Windows Installer在中國(guó)的很多計(jì)算機(jī)上還不能算普及,這也使得.NET Framework開發(fā)出來的應(yīng)用程序更像是玩具而不是用來解決實(shí)際問題的。筆者有一個(gè)很好的朋友,調(diào)試了近兩個(gè)小時(shí)也沒把.NET Framework裝上,原因是他的Windows XP會(huì)在安裝.NET Framework時(shí)提示拒絕訪問Windows Installer服務(wù)。
C++Builder的應(yīng)用程序兼容性一直是Borland所自豪的,這種兼容性甚至還包括了跨平臺(tái)的可移植性。在這點(diǎn)上,自私的微軟是不可能做到的。在我們剛剛提到的那個(gè)例程中,一個(gè)編譯好的EXE文件(可以獨(dú)立運(yùn)行,不需要BPL或DLL)也僅是529KB。雖然Visual C# .NET的目標(biāo)程序更小,但23.2MB的“先決條件”已經(jīng)扼殺了大量寶貴的用戶群。
綜上所述,Visual C# .NET的新特性對(duì)于提高編程效率,改善編程體驗(yàn)有著重要的意義,但是微軟應(yīng)該放下自己的老大架子,再花心思好好提升一下軟件的運(yùn)行效率,.NET Framework才能真正被廣大程序員所接受。不然,C#帶來的開發(fā)上的方便并不會(huì)吸引那些有編程經(jīng)驗(yàn)的程序員們,因?yàn)閷?duì)于絕大多數(shù)程序員來說,程序的健壯性是最重要的。相信微軟也不希望.NET戰(zhàn)略的核心——.NET Framework只是一個(gè)初學(xué)者的玩具。
Visual C#.NET前途光明,要走的路卻十分曲折,讓我們拭目以待吧。