.net

.net

.NET 是 Microsoft XML Web services 平台。XML Web services 允許應用程式通過 Internet 進行通訊和共享數據,而不管所採用的是哪種作業系統、設備或程式語言。Microsoft .NET 平台提供創建 XML Web services 並將這些服務集成在一起之所需。2014年4月4日,微軟成立.NET基金會去管理和引導開源組件的開發;2014年11月13日,微軟宣布將免費提供Visual Studio Community 2013。

基本信息

概要

.net.net
.NET就是微軟用來實現XML,WebServices,SOA(面向服務的體系結構service-orientedarchitecture)和敏捷性的技術。

.NET也可以如下來定義:.NET是微軟的新一代技術平台,為敏捷商務構建互聯互通的套用系統,這些系統是基於標準的,聯通的,適應變化的,穩定的和高性能的。

從技術的角度,一個.NET套用是一個運行於.NETFramework之上的應用程式。(更精確的說,一個.NET套用是一個使用.NETFramework類庫來編寫,並運行於公共語言運行時CommonLanguageRuntime之上的應用程式。)如果一個應用程式跟.NETFramework無關,它就不能叫做.NET程式。比如,僅僅使用了XML並不就是.NET套用,僅僅使用SOAPSDK調用一個WebService也不是.NET套用。.NET是基於Windows作業系統運行的操作平台,套用於網際網路的分散式。

開源

微軟在Build開發者大會上宣布開源一批.NET庫和相關技術,成立.NET基金會去管理和引導開源組件的開發。微軟還將在Apache2.0許可證下開源Roslyn編譯器堆疊,Roslyn是微軟所謂的編譯器即服務,包含了C#和VisualBasic.NET編譯器。.NET基金會由來自微軟、GitHub和Xamarin的代表組成,Xamarin由GNOME創始人MigueldeIcaza等人創建,開發.NET開源實現。Xamarin向基金會貢獻了它的部分庫。deIcaza在接受採訪時表示,微軟已經變了,不僅僅移除了許可證中的限制,而且與Xamarin合作徵求設計反饋,在創作共用許可證下發布文檔。

2014年4月的Build開發者大會上,微軟宣布開源一批.NET庫和相關技術,成立.NET基金會去管理和引導開源組件的開發。微軟還將在Apache2.0許可證下開源Roslyn編譯器堆疊,Roslyn是微軟所謂的編譯器即服務,包含了C#和VisualBasic.NET編譯器。.NET基金會由來自微軟、GitHub和Xamarin的代表組成,Xamarin由GNOME創始人MigueldeIcaza等人創建,開發.NET開源實現。Xamarin向基金會貢獻了它的部分庫。deIcaza在接受採訪時表示,微軟已經變了,不僅僅移除了許可證中的限制,而且與Xamarin合作徵求設計反饋,在創作共用許可證下發布文檔。

2014年11月13日,為了進一步擴大雲計算市場,微軟將不再把.NET和VisualStudio等關鍵軟體技術局限在Windows平台,今後還將兼容Linux、MacOSX、iOS和Android。除此之外,微軟還宣布將開放.NET核心伺服器運行環境和框架的原始碼,使得外部開發者也可以對這一軟體開發平台做出貢獻。

2014年11月14日,宣布將免費提供VisualStudioCommunity2013,作為這一變化的一部分,微軟將允許開發者使用.NET運行環境和框架,來為Linux和Mac開發基於伺服器和雲端的套用。並將免費對獨立開發者、學生、小企業等用戶開放。

域名

.net是國際最廣泛流行的通用域名格式。一般用於從事Internet相關的網路服務的機構或公司,是建立全球商業品牌,國際化形象的第一選擇。

套用組件

客戶端套用

組成.net軟體技術的組件,組件之一,“智慧型”客戶端套用軟體和作業系統,包括PC、PA、手機或其他移動設備通過網際網路、藉助WebServices技術,用戶能夠在任何時間、任何地點都可以得到需要的信息和服務。例如:可以在手機上閱讀新聞、定購機票、瀏覽線上相冊等等。CRM系統,套用了.NET的解決方案後所有的業務人員便可以通過手機或PDA直接訪問客戶信息了。

WebServices
WebServices是智慧型終端軟體的基礎,微軟為用戶創建智慧型終端提供了一整套豐富的解決方案,包括:
.NETFramework-智慧型終端實現跨平台(設備無關性)的
VisualStudio.NET–建立並集成WebServices和應用程式的快速開發工具
MicrosoftWindowsServer2003–新一代的企業伺服器,用於提供建立和發布各種解決方案
MicrosoftOfficeProfessionalEdition2003–內建的工具集也能幫助開發智慧型終端
.net
WebServices是.NET的核心技術。那什麼是WebServices呢?正如Web是新一代的用戶與套用互動的途徑,XML是新一代的程式之間通訊的途徑一樣,WebServices是新一代的計算機與計算機之間一種通用的數據傳輸格式,可讓不同運算系統更容易進行數據交換。WebServices有以下幾點特性:Webservices允許套用之間共享數據;Webservices分散了代碼單元;基於XML這種internet數據交換的通用語言,實現了跨平台、跨作業系統、跨語言。那微軟的ASP和Webservices究竟有什麼不同呢,ASP仍然是一個集中式計算模型的產物,只不過是披著一層網際網路的外衣。但WebServices卻是一個迥然不同的精靈,它秉承“軟體就是服務”的真言,同時順應分散式計算模式的潮流。而它的存在形式又與以往軟體不同。這種組件模式,小巧、單一,對於開發人員來講,開發成本較低。
在這裡指出Webservices不是微軟發明的,同樣也不屬於微軟專有。Webservices是一個開放的標準,和HTTP、XML、SOAP一樣。他們是一個工業標準而非微軟標準,WS-I是為了促進WebServices互通性的聯盟組織,最初是由IBM和微軟所發起,其它的成員包括BEASystem、惠普計算機(HP)、甲骨文(Oracle)、英特爾(Intel)和SUN計算機(SunMicrosystem)。如今網路上存在的大多Webservices其實沒有使用.NET構架,Webservices具有互操作屬性,你同樣可以使用Windows開發客戶端來調用運行於Linux上面的Webservices的方法。

接口規範

.net.net
提到的接口規範問題,在.NET中,Webservice接口通常使用WebServicesDescriptionLanguage(WSDL)描述。WSDL使用XML來定義這種接口操作標準及輸入輸出參數,看起來很像COM和CORBA的接口定義語言(IDLS)InterfaceDefinitionLanguages。接口定義後就必須使用一些協定調用接口,如SOAP協定,SOAP源於一種叫做XMLRPC(XML遠程進程調用remoteprocedurecalling)的協定,而Java則根據XML-RPC發展了自己的JAX-RPC協定用來調用WebServices。發布和訪問WebServices的接口就用到UDDI了,這裡我們只需要知道WSDL使用XML定義WebServices接口,通過SOAP訪問WebServices,在internet上尋找WebServices使用UDDI就行了。伺服器架構——MicrosoftWindowsServerSystem Microsoft提供了最佳的伺服器構架—MicrosoftWindowsServerSystem—便於發布、配置、管理、編排WebServices。為了滿足分散式計算的需要微軟構造了一系列的伺服器系統,這些內建安全技術的系統全部支持XML,這樣加速了系統、應用程式以及同樣使用WebServices的夥伴套用之間的集成。
MicrosoftWindowsServerSystem包括:
MicrosoftApplicationCenter2000-配置和管理Web應用程式
MicrosoftBizTalkServer2002-建立基於XML的跨套用和組織的商業邏輯
visualstudio.net
MicrosoftCommerceServer2002–能夠迅速建立大規模電子商務的解決方案
MicrosoftContentManagementServer2002–管理動態電子商務網站的目錄
MicrosoftExchangeServer2000–用於進行隨時隨地的通訊協作
MicrosoftHostIntegrationServer2000–用於和主機系統之間傳輸數據
MicrosoftInternetSecurityandAccelerationServer2000(ISAServer)–internet連線
MicrosoftMobileInformationServer2002–用於支持手持設備
MicrosoftOperationsManager2000–描述企業級解決方案的操作管理
MicrosoftProjectServer2002-提供項目管理的最佳方案
MicrosoftSharePointPortalServer2001–查詢、共享、發布商業信息
MicrosoftSQLServer2000–企業級資料庫
MicrosoftVisualStudio.NET和Microsoft.NETFramework對於建立,發布並運行WebServices是一個完美的解決方案。

CLR與CIL

.NET的
NETFramework環境
初級組成是CIL和CLR。CIL是一套運作環境說明,包括一般系統、基礎類庫和與機器無關的中間代碼,全稱為通用中間語言(CIL)。CLR則是確認操作密碼符合CIL的平台。在CIL執行前,CLR必須將指令及時編譯轉換成原始機械碼。
所有CIL(通用中間語言)都可經由.NET自我表述。CLR檢查元資料以確保正確的方法被調用。元資料通常是由語言編譯器生成的,但開發人員也可以通過使用客戶屬性創建他們自己的元資料。
如果一種語言實現生成了CIL,它也可以通過使用CLR被調用,這樣它就可以與任何其他.NET語言生成的資料相互動。CLR也被設計為作業系統無關性。
當一個彙編體被載入時,CLR執行各種各樣的測試。其中的兩個測試是確認與核查。在確認的時候,CLR檢查彙編體是否包含有效的元資料和CIL,並且檢查內部表的正確性。核查則不那么精確。核查機制檢查代碼是否會執行一些“不安全”的操作。核查所使用的演算法非常保守,導致有時一些“安全”的代碼也通不過核查。不安全的代碼只有在彙編體擁有“跳過核查”許可的情況下才會被執行,通常這意味著代碼是安裝在本機上的。
通過.NET,你可以用SOAP和不同的Webservices進行互動。

依賴關係

每個新版本的.NETFramework都會保留早期版本中的功能並會添加新功能。CLR由其自己的版本號確定的。某些版本的.NETFramework包含新版本的CLR,而其他版本的.NETFramework使用早期版本的CLR。例如,.NETFramework4包含CLR4,而.NETFramework3.5包含CLR2.0。(沒有版本3的CLR。)雖然.NETFramework4.5是.NETFramework4的就地更新,基礎CLR版本號成為CLR4.5。
通常,您不應卸載計算機上安裝.NETFramework的任何版本,因為您使用的應用程式可能取決於特定版本,並且可能中斷,如果移除該版本。您可以同時在一台計算機上載入.NETFramework的多個版本。這意味著可以安裝.NETFramework,而無需卸載舊版本。

2.0版本

完整版號-2.0.50727.42,發布於2005年10月27日。
.NET框架2.0的組件都包含在VisualStudio2005和SQLServer2005裡面。通過MSDNUniverse版可以免費下載RTM版本。
自1.1版本以來的改進:
大量的API變更。
新的API讓需要管理.NET運行庫實例的非.NET的應用程式可以做到這點。這個新的API對.NET運行庫的各種功能,包括:多執行緒、存儲器分配、代碼載入等,提供了很好的控制。它最初是為MicrosoftSQLServer能夠有效率的使用.NET運行庫而設計的,因為MicrosoftSQLServer擁有它自己的日程管理器和存儲器管理器。

4.5版本

.NET框架4.5是.NET框架4高兼容性的就地更新(in-placeupdate)。搭配C#或VisualBasic程式設計語言使用.NET框架4.5,即可編寫WindowsStore風格的應用程式。.NET框架4.5可提升性能、可靠度及安全性。於2012年8月15日推出。但請注意,.NET框架4.5不支持WindowsXP作業系統。

4.0版本

.NETFramework4.0,英文版於2010年4月12日推出。
主要的新特性有以下幾個方面:
動態編程
並行計算
後期綁定
協變與逆變
接下來我們一一領略C#4.0中的語言特性。

動態編程

C#是靜態強類型語言。而在很多情況下,提供“動態”行為,是常常發生的事情,例如通過反射在運行時訪問.NET類型、調用動態語言對象、訪問COM對象等,都無法以靜態類型來獲取。因此,C#4.0引入的又一個全新的關鍵字dynamic,也同時引入了改善靜態類型與動態對象的互動能力,這就是動態查找(DynamicLookup)例如:
publicstaticvoidMain(){
dynamicd=GetDynamicObject();
d.MyMethod(22);//方法調用
d.A=d.B;//屬性賦值
d[“one”]=d[“two”];//索引器賦值
inti=d+100;//運算符調用
strings=d(1,2);//委託調用
}
就像一個object可以代表任何類型,dynamic使得類型決斷在運行時進行,方法調用、屬性訪問、委託調用都可動態分派。同時,動態特性還體現在構建一個動態對象,在C#4.0實現IDynamicObject接口的類型,可以完全定義動態操作的意義,通過將C#編譯器作為運行時組件來完成由靜態編譯器延遲的操作,例如:
dynamicd=newFoo();
strings;
d.MyMethod(s,3,null);
在具體執行過程中,C#的運行時綁定器基於運行時信息,通過反射獲取d的實際類型Foo,然後在Foo類型上就MyMethod方法進行方法查找和重載解析,並執行調用,這正是動態調用的背後秘密:DLR。在.NET4.0中將引入重要的底層組件DLR(DynamicLanguageRuntime,動態語言運行時),除了實現動態查找的基礎支持,DLR也同時作為基礎設施為類似於IronRuby、IronPython這樣的動態語言提供統一的互操作機制。總而言之,動態編程將為C#在以下領域產生巨大的變革:
·Office編程與其他COM互動。
·動態語言支持,在C#中消費IronRuby動態語言類型將並非難事,體驗動態語言特性指日可待。
·增強反射支持。
以調用IronRython為例,我們只需引入IronPython.dll,IronPython.Modules.dll,andMicrosoft.Scripting.dll,即可通過創建ScriptRuntime在C#中HostingIronPython環境,進而來操作動態語言的類型信息。
ScriptRuntimepy=Python.CreateRuntime();
dynamicmypy=py.UseFile("myfile.py");
Console.WriteLine(mypy.MyMethod("Hello"));
雖然從微軟當前提供的技術資料和CTP演示中,動態查找還存在或多或少的問題,但是在“動態”大行其道的今天,我們無法迴避也必須擁抱這個未來的主角,因為我堅信明天會更好。

並行計算

.net.net
並行計算的出現,是計算機科學發展的必然結果,隨著計算機硬體的迅猛發展,在多核處理器上工作已經是既存事實,而傳統的編程模式必須兼容新的硬體環境才能使計算機性能達到合理的套用效果。用Anders大師的話說:未來5到10年,並行計算將成為主流程式語言不可忽視的方向,而4.0為C#打響了實現並發的第一槍。
未來的.NETFramework4.0中將集成TPL(TaskParallelLibrary)和PLINQ(ParallelLINQ),這也意味著未來我們可以套用C#4.0實現並行化套用,在統一的工作調度程式下進行硬體的並行協調,這將大大提高應用程式的性能同時降低現存並發模型的複雜性。
那么,我們應該一睹為快套用C#武器來開發並發環境下的超酷感受,在System.Threading.Parallel靜態類提供了三個重要的方法For、Foreach、Invoke可以為我們小試牛刀:
//套用TPL,執行並行循環任務
Parallel.For(0,10,i=>{DoSomething(i);});
線上程爭用執行情況下,相同的操作在雙核平台下運行,以StopWatch進行精確時間測試,並行環境下的執行時間為2001ms,而非並行環境下的執行時間為4500ms,並行運算的魅力果然名不虛傳。我們再接再厲套用PLINQ執行對於並行運算的查詢、排序等,當前PLINQ支持兩種方式ParallelEnumerable類和ParallelQuery類,例如:
int[]data=newint[]{0,1,2,3,4,5,6,7,8,9};
int[]selected=(fromxindata.AsParallel()
selectx+1).ToArray();
更詳細的對比示例留待讀者在實踐中對此進行討論,並行計算為託管代碼在多核環境下的性能最佳化提供了統一的解決方案,而未來我們會做的更好。
備註:實際上,我們可以選擇下載安裝MicrosoftParallelExtensionstothe.NETFramework3.5June2008CTP包,就可以在.NET3.5環境下體驗並行計算的無窮魅力。

協變和逆變

協變和逆變,是為解決問題而生的。而要理清解決什麼樣的問題,需要首先從理清幾個簡單的概念開始。首先我們進行一點操作:
Derivedd=newDerived();
Baseb=d;
Derived類型繼承自Based類型,由Derived引用可以安全的轉換為Based引用,而這種轉換能力可以無縫的實現在Derived數組和Base數組,例如:
Derived[]ds=newDerived;
Base[]bs=ds;
而這種原始轉換(由子類轉換為父類)方向相同的可變性,被稱為協變(covariant);其反向操作則被稱為逆變(contravariant)。當同樣的情形套用於泛型時,例如:
List<Derived>ds=newList<Derived>();
List<Base>bs=ds;
類似的操作卻是行不通的。所以,這就成為C#4.0中完善的問題——泛型的協變與逆變:
List<Base>bs=newList<Base>();List<Derived>ds=newList<Derived>();
bs=ds;//List<T>;支持對T協變
ds=bs;//List<T>;支持對T逆變
而在C#4.0中,伴隨著協變與逆變特性的加入,C#引入兩個in和out關鍵字來解決問題。
publicinterfaceICovariant<outT>{
TMyAction();
}
publicinterfaceIContravariant<inT>
{
voidMyAction(Targ);
}
其中,out表示僅能作為返回值的類型參數,而in表示僅能作為參數的類型參數,不過一個接口可以既有out又有in,因此既可以支持協變、支持逆變,也可以同時支持,例如:
publicinterfaceIBoth<outU,inV>
{
}

默認參數

.net.net
命名參數和可選參數是兩個比較簡單的特性,對於熟悉其他程式語言的開發者來說可選參數並不陌生,為參數提供默認值時就是可選參數:
publicvoidMyMethod(intx,inty=10,intz=100){
}
因此,我們可以通過調用MyMethod(1)、MyMethod(1,2)方式來調用MyMethod方法。而命名參數解決的是傳遞實參時,避免因為省去默認參數造成的重載問題,例如省去第二個參數y調用時,即可通過聲明參數名稱的方式來傳遞:
MyMethod(20,z:200);
相當於調用MyMethod(20,10,200),非常類似於Attribute的調用方式。雖然只是小技巧,但也同時改善了方法重載的靈活性和適配性,體現了C#語言日趨完美的發展軌跡。
當然,除此之外.NET4.0還增加了很多值得期待的平台特性,也將為C#編碼帶來前所未有的新體驗。
以上相關著作權歸作者。

3.0版本

.NETFramework3.0(曾用名WinFX)是微軟為作業系統WindowsVista(舊稱“Longhorn”)而特別設計的API。.NETFramework是對.NET架構和Win32API的擴展。雖然Win32API仍然存在於WindowsVista中,但是在WinFX中不能通過它直接調用。另外,WinFX將提供給.NET程式設計師更加簡便地方式來調用Windows中的功能。
.NETFramework3.0同樣能在WindowsXP和WindowsServer2003的計算機上運行,這樣增加了能夠運行.NETFramework3.0程式的計算機數量。由於向後兼容,能夠更加容易將這些技術介紹給開發人員和最終用戶。2006年9月1日,微軟發布了.NETFramework3.0的RC版本,開發人員能夠無需安裝Vista就可以體驗這些新的技術。
.NETFramework3.0並沒有新版本的CLR,而是在.NETFramework2.0的基礎上增加了幾個新的部件,所以並沒有任何程式設計語言有新的語法特性,如果要安裝.NETFramework3.0,則必須先安裝.NETFramework2.0,.NETFramework3.0可以完全向下兼容.NETFramework2.0。
.NETFramework3.0主要由的四部分組成:
WPF(WindowsPresentationFoundation),內部代碼“Avalon”,是一套基於XAML(eXtensibleApplicationMarkupLanguage)、.NET和矢量圖技術的全新的圖形界面系統和API,它充分利用了計算機的3D顯示卡硬體功能和Direct3D技術。
WCF(WindowsCommunicationFoundation),內部代碼“Indigo”,是一個面向服務的通訊框架,利用它可以實現本地和遠程的程式之間的互動。
WF(WorkflowFoundation)於2005年8月公開,微軟提供的工作流引擎,通過它可以實現任務的自動化和事務的集成。
InfoCard是一個軟體組件的代碼,用來安全的保存和使用用戶的數字身份,並提供統一的界面來針對特定的事務選擇身份,例如登入一個網站。

3.0特性

類型化變數
這個特性非常簡單,有些JavaScript的影子,我們可以統一使用使用"var"關鍵字來聲明局部變數,而不再需要指明變數的確切類型了,變數的確切類型可通過聲明變數時的初始值推斷出來。這樣一來,可以大大簡化我們聲明局部變數的工作量了,下面是一個例子:
classLocalVariables:AppRunner.AbstractApplication
{
publicoverridevoidRun()
{
varintValue=5;
varstringValue="Thisisastring";
varcustomClass=newLocalVariables();
varintArray=newint{1,2,3};
foreach(varvalueinintArray)
Console.WriteLine(value);
}
}
上面的代碼將被解析成:
classLocalVariables:AppRunner.AbstractApplication
{
publicoverridevoidRun()
{
intintValue=5;
stringstringValue="Thisisastring";
LocalVariablescustomClass=newLocalVariables();
int[]intArray=newint;
foreach(intvalueinintArray)
Console.WriteLine(value);
}
}
要特別注意的是,由於變數的類型是通過變數初始值推斷而來的,所以在聲明變數的同時必需為變數指定初始值。並且,變數並不是沒有類型的,變數一旦初始化之後,類型就確定下來了,以後就只能存儲某種類型的值了,比如上面的stringValue的類型經推斷為string,所以該變數就只能保存string類型的值了。

匿名類型

有些時候我們需要臨時保存一些運算的中間結果,特別是當這些中間結果是由多個部份組成時,我們常常會去聲明一個新的類型,以方便保存這些中間結果。表面上看起來這很正常,而細想之後就會發現,這個新類型只服務於這個函式,其它地方都不會再使用它了,就為這一個函式而去定義一個新的類型,確實有些麻煩。
C#3.0中的匿名類型特性就可以很好的解決上面提到的問題,通過匿名類型,我們可以簡單使用new{屬性名1=值1,屬性名2=值2,.....,屬性名n=值n}的形式直接在函式中創建新的類型,看下面這個例子:
classAnonymousType:AppRunner.AbstractApplication
{
publicoverridevoidRun()
{
varanonymousType1=new{
CardNumber="10001",Name="van’s",Sex=true
};
Console.WriteLine(anonymousType1.CardNumber);
Console.WriteLine(anonymousType1.Name);
varanonymousType2=new{
CardNumber="10002",Name="martin",Sex=true
};
anonymousType2=anonymousType1;
}
}
在新類型中只能有欄位成員,而且這些欄位的類型也是通過初值的類型推斷出來的。如果在聲明新的匿名類型時,新類型的欄位名、順序以及初始值的類型是一致的,那么將會產生相同的匿名類型,所以上例中anonymousType1和anonymousType2的類型是相同的,自然能進行anonymousType2=anonymousType1的賦值。
類型化數組
這個特性是對隱式類型化本地變數的擴展,有了這個特性,將使我們創建數組的工作變得簡單。我們可以直接使用"new[]"關鍵字來聲明數組,後面跟上數組的初始值列表。在這裡,我們並沒有直接指定數組的類型,數組的類型是由初始化列表推斷出來的。
classAnonymousTypeArray:AppRunner.AbstractApplication
{
publicoverridevoidRun()
{
varintArray=new[]{1,2,3,4,5};
vardoubleArray=new[]{3.14,1.414};
varanonymousTypeArray=new[]{
new{Name="van’s",Sex=false,Arg=22},
new{Name="martin",Sex=true,Arg=23}
};
Console.WriteLine(intArray);
Console.WriteLine(doubleArray);
Console.WriteLine(anonymousTypeArray[0].Name);
}
}
上面的代碼中,anonymousTypeArray變數的聲明同時運用了隱式類型化數組和匿名類型兩種特性,首先創建匿名類型,然後再初始值列表,推斷出數組的確切類型。

對象構造者

我們在聲明數組時,可以同時對其進行初始化,這樣就省去了很多麻煩,但是在創建類的對象時,這招可就不靈了,我們要么調用該類的構造函式完成對象的初始化,要么就手工進行初始化。這兩種方法都不太方便,使用構造函式來對對象進行初始化時,我們為了某種靈活性,可能需要編寫構造函式的多個重載版本,實在是麻煩。
C#3.0中加入的對象構造者特性,使得對象的初始化工作變得格外簡單,我們可以採用類似於數組初始化的方式來初始化類的對象,方法就是直接在創建類對象的表達式後面跟上類成員的初始化代碼。具體示例如下:
classPoint
{
publicintX{get;set;}
publicintY{get;set;}
publicoverridestringToString()
{
return"("+X.ToString()+","+Y.ToString()+")";
}
}
classRectangle
{
publicPointP1{get;set;}
publicPointP2{get;set;}
publicRectangle()
{
P1=newPoint();
P2=newPoint();
}
publicoverridestringToString()
{
return"P1:"+P1+",P2:"+P2;
}
}
classObjectBuilder:AppRunner.AbstractApplication
{
publicoverridevoidRun()
{
PointthePoint=newPoint(){X=1,Y=2};
Console.WriteLine("Point(X,Y)=",thePoint);
RectangletheRectangle=newRectangle(){
P1={X=1,Y=1},P2={X=100,Y=200}
};
Console.WriteLine(theRectangle);
}
}
我們在定義Point類的X和Y屬性時,只須寫上該屬性的get和set訪問器聲明,C#編譯器會自動為我們生成默認的get和set操作代碼,當我們需要定義簡單屬性時,這個特性非常有用。
我們以newPoint(){X=1,Y=2}語句,輕鬆的完成了對Point類的初始化工作。在創建類的對象時,我們可以按照需要去初始化類的對象,只要在類的創建表達式後跟上要初始化屬性的列表即可,且可以只對需要初始化的屬性賦初值,而無需把所有屬性的初始值都寫上去。
在theRectangle對象的初始化表達式中,我們首先對P1屬性進行初始化,然而P1屬性也是一個自定義的類型,所以P1屬性的初始化是另一個類型(Point)的初始化表達式,我們可以這樣的方式來對更加複雜的類型進行初始化。
上篇文章中介紹了C#3.0中比較簡單的四個特性,分別是隱式類型化本地變數、匿名類型、隱式類型化數組,以及對象構造者,下面我將對C#3.0中的較複雜,同時也是非常強大的幾個特性進行介紹,供大家快速瀏覽。

集合構造者

我們可以在聲明數組的同時,為其指定初始值,方法是直接在數組聲明的後面跟上初始值列表。這樣就使數組的初始化工作變得簡單,而對於我們自己創建的集合類型,就無法享受到與普通數組一樣的待遇了,我們無法在創建自定義集合對象的同時,使用數組的初始化語法為其指定初始值。
C#3.0中加入的集合構造者特性,可使我們享受到與普通數組一樣的待遇,從而在創建集合對象的同時為其指定初始值。為了做到這一點,我們需要讓我們的集合實現ICollection<T>;接口,在這個接口中,完成初始化操作的關鍵在於Add函式,當我使用初始化語法為集合指定初始值時,C#編譯器將自動調用ICollection<T>;中的Add函式將初始列表中的所有元素加入到集合中,以完成集合的初始化操作。使用示例如下:
classCollectionInitializer:AppRunner.AbstractApplication
{
classStringCollection:ICollection<string>
{
publicvoidAdd(stringitem)
{
Console.WriteLine(item);
}
//OtherICollection<T>Members
}
publicoverridevoidRun()
{
StringCollectionstrings=newStringCollection(){"Van's","Brog","Vicky"};
}
}
在這個示例中,編譯器會自動為strings對象調用Add方法,以將初始值列表中的所有元素加入到集合中,這裡我們只是簡單將初始值列表中的元素輸出到控制台。
Lambda表達式
C#2.0中加入的匿名代理,簡化了我們編寫事件處理函式的工作,使我們不再需要單獨聲明一個函式來與事件綁定,只需要使用delegate關鍵字線上編寫事件處理代碼。
而C#3.0則更進一步,通過Lambda表達式,我們可以一種更為簡潔方式編寫事件處理代碼,新的Lambda事件處理代碼看上去就像一個計算表達式,它使用"=>"符號來連線事件參數和事件處理代碼。我可以這樣寫:SomeEvent+=事件參數=>事件處理代碼;下面是完整的示例:
delegateTAddDelegate<T>(Ta,Tb);
classLambdaExpression:AppRunner.AbstractApplication
{
publicstaticeventEventHandlerMyEvent;
publicoverridevoidRun()
{
MyEvent+=delegate(objects,EventArgse)
{
Console.WriteLine(s);
};
MyEvent+=(s,e)=>{Console.WriteLine(s);};
MyEvent(this,null);
AddDelegate<string>add=(a,b)=>a+b;
Console.WriteLine(add("Lambda","Expression"));
}
}
在上面的例子中,分別使用了匿名代理和Lambda表達式來實現同樣的功能,可以明顯看出Lambda表達式的實現更為簡潔。我們在使用Lambda表達式編寫事件處理代碼時,無需指明事件參數的類型,且返回值就是最後一條語句的執行結果。
擴展方法
當我們需要對已有類的功能進行擴展時,我們通常會想到繼承,繼承已有類,然後為其加入新的行為。而C#3.0中加入的擴展方法特性,則提供了另一種實現功能擴展的方式,我們可以在不使用繼承的前提下實現對已有類本身的擴展,這種方法並不會產生新的類型,而是採用向已有類中加入新方法的方式來完成功能擴展。
在對已有類進行擴展時,我們需將所有擴展方法都寫在一個靜態類中,這個靜態類就相當於存放擴展方法的容器,所有的擴展方法都可以寫在這裡面。而且擴展方法採用一種全新的聲明方式:publicstatic返回類型擴展方法名(this要擴展的類型sourceObj[,擴展方法參數列表]),與普通方法聲明方式不同,擴展方法的第一個參數以this關鍵字開始,後跟被擴展的類型名,然後才是真正的參數列表。下面是使用示例:
staticclassExtensions
{
publicstaticintToInt32(thisstringsource)
{
returnInt32.Parse(source);
}
publicstaticT[]Slice<T>(thisT[]source,intindex,intcount)
{
if(index<0||count<0||index+count>source.Length)
{
thrownewArgumentException();
}
T[]result=newT[count];
Array.Copy(source,index,result,0,count);
returnresult;
}
}
classExtensionMethods:AppRunner.AbstractApplication
{
publicoverridevoidRun()
{
stringnumber="123";
Console.WriteLine(number.ToInt32());
int[]intArray=newint[]{1,2,3};
intArray=intArray.Slice(1,2);
foreach(variinintArray)
Console.WriteLine(i);
}
}
在上面的示例中,靜態的Extensions類中有兩個擴展方法,第一個方法是對string類的擴展,它為string類加入了名為ToInt32的方法,該方法沒有參數,並返回一個int類型的值,它將完成數字字元向整數的轉換。有了這個擴展方法之後,就可對任意string類的對象調用ToInt32方法了,該方法就像其本身定義的一樣。
第二個擴展方法是一個范型方法,它是對所有數組類型的擴展,該方法完成數組的切片操作。
C#3.0中的Linq表達式,就是大量運用擴展方法來實現數據查詢的。
Linq表達式
C#3.0中加入的最為複雜的特性就是Linq查詢表達式了,這使我們可直接採用類似於SQL的語法對集合進行查詢,這就使我們可以享受到關係數據查詢的強大功能。
Linq查詢表達式是建立在多種C#3.0的新特性之上的,這也是我為什麼最後才介紹Linq的原因。下面看一個例子:
classLinqExpression:AppRunner.AbstractApplication
{
publicoverridevoidRun()
{
//定義匿名數組persons,並為其賦初值
varpersons=new[]{
new{Name="Van's",Sex=false,Age=22},
new{Name="Martin",Sex=true,Age=30},
new{Name="Jerry",Sex=false,Age=24},
new{Name="Brog",Sex=false,Age=25},
new{Name="Vicky",Sex=true,Age=20}
};
/*
執行簡單Linq查詢
檢索所有年齡在24歲以內的人
查詢結果放在results變數中
results變數的類型與數組persons相同
*/
varresults=frompinpersons
wherep.Age<=24
selectp;
foreach(varpersoninresults)
{
Console.WriteLine(person.Name);
}
Console.WriteLine();
//定義匿名數組customers,並為其賦初值
//該數組是匿名類型的
varcustomers=new[]{
new{
Name="Van's",City="China",Orders=new[]{
new{
OrderNo=0,
OrderName="C#ProgrammingLanguage(SecondEdition)",
OrderDate=newDateTime(2007,9,5)
},
new{
OrderNo=1,
OrderName="HeadFirstDesignPatterns(ChineseEdition)",
OrderDate=newDateTime(2007,9,15)
},
new{
OrderNo=2,
OrderName="asp.netUnleashed2.0(ChineseEdition)",
OrderDate=newDateTime(2007,09,18)
},
new{
OrderNo=3,
OrderName="TheC++ProgrammingLangauge(SpecialEdition)",
OrderDate=newDateTime(2002,9,20)
}
}
},
new{
Name="Brog",City="China",Orders=new[]{
new{
OrderNo=0,
OrderName="C#ProgrammingLanguage(SecondEdition)",
OrderDate=newDateTime(2007,9,15)
}
}
},
new{
Name="Vicky",City="London",Orders=new[]{
new{OrderNo=0,
OrderName="C++ProgrammingLanguage(SpecialEdition)",
OrderDate=newDateTime(2007,9,20)
}
}
}
};
/*
執行多重Linq查詢
檢索所在城市為中國,且訂單日期為2007年以後的所有記錄
查詢結果是一個匿名類型的數組
其中包含客戶名,訂單號,訂單日期,訂單名四個欄位
*/
varsomeCustomers=fromcincustomers
wherec.City=="China"
fromoinc.Orders
whereo.OrderDate.Year>=2007
selectnew{c.Name,o.OrderNo,o.OrderDate,o.OrderName};
foreach(varcustomerinsomeCustomers)
{
Console.WriteLine(
customer.Name+","+customer.OrderName+","+
customer.OrderDate.ToString("D")
);
}
}
}
從上面的例子中,我們可以看到Linq查詢的強大特性,它允許我們進行簡單查詢,或者進行更為複雜的多重連線查詢。且查詢的結果還可以是自定義的匿名類型。

3.5特性

快速指南
VS2008的多定向支持
VS2008允許你構建針對多個.NET框架版本的套用。你可以從下面的部落格貼子裡進一步了解其中的工作原理:
VS2008Multi-TargetingSuort
VS2008Web設計器和C支持
VS2008包含一個顯著改進的HTMLweb設計器。該設計器提供了分割視圖編輯,嵌套母板頁,以及出色的C集成。
A.NET還提供了一個新的控制項,該控制項對數據UI場景提供了非常靈活的支持,允許對輸出的標識做完全的定製,與VS2008中的新C支持還有良好的協作。
A.NETAJAX和JavaScript支持
.NET3.5內置提供A.NETAJAX,還添加了支持Weart的UpdatePanel,支持JSON的WCF,以及N個缺陷修補和性能改進等方面的新特性。VS2008還對集成JavaScript和AJAX進你的套用提供了極棒的支持:
VS2008JavaScriptIntellisee
VS2008JavaScriptDebugging
改進和LINQ
VS2008中的新VB和C#編譯器對這些語言做了顯著的改進。兩者都添加了函式式編程概念的支持,允許你編寫更乾淨,更簡潔,更具有表達性的代碼。這些特性還促成了我們稱之為LINQ(語言級集成查詢)的新編程模型,使得查詢和運算元據成為.NET中的一等編程概念。
下面是我撰寫的一些討論這些新語言特性的文章(用C#作為示例):
自動屬性,對象初始化器,和集合初始化器
擴展方法
Lambda表達式
查詢句法
匿名類型
LINQtoSQL中的數據訪問改進
LINQtoSQL是.NET3.5中內置的OR/M(對象關係映射器)。它允許你使用.NET對象模型對關係資料庫進行建模。然後你可以使用LINQ對資料庫進行查詢,以及更新、插入,刪除數據。LINQtoSQL完整支持事務,視圖和存儲過程。它還提供了一個把業務邏輯和驗證規則結合進你的數據模型的簡易方式。下面是一些我討論如何使用LINQtoSQL的文章:
Part1:IntroductiontoLINQtoSQL
Part2:DefiningourDataModelClaes
Part3:QueryingourDatabase
Part4:UpdatingourDatabase
Part5:BindingUIusingtheA:LinqDataSourceControl
我會在以後的幾周內再往這個系列裡添加幾篇文章。我認為你會發現LINQtoSQL顯著地簡化了構建非常乾淨的數據模型以及編寫極其乾淨的數據代碼。
其他改進
上面的列表只是所做改進的一小部分。針對客戶端開發,VS2008包含了WPF設計器和項目支持。ClickOnce和WPFXBA在FireFox中也工作了。WinForms和WPF項目也能使用A.NET套用服務(成員,角色和用戶數據)來漫遊用戶數據了。辦公開發也更加豐富了,包括對Office2007Rion的集成支持。WCF和Workflow項目和設計器也包括在VS2008中了。單元測試的速度大為提高,而且單元測試的支持包括在VSProfeional版本(而不僅僅是VSTS版了)中了。連續集成支持也內置於TFS中了。AJAXweb測試(單元和壓力)也由VSTest產品支持了。還有許許多多多的改進,這裡無法一一提及了。
注意事項
在安裝VS2008和.NET3.5Beta2之後,還有2件重要的事情你應該馬上做:
1)你應該下載和運行這個批檔案。這隻要幾秒鐘就可以運行完,它修補了這個星期早些時候我們發現的System.Web.Exteio.dll版本政策的問題,該程式集包含了A.NETAJAX。如果你不運行這個批檔案,那么用A.NETAJAX1.0和VS2005構建的現有的A.NET2.0項目就會自動地運載隨.NET3.5Beta2發布的新A.NETAJAX版本。這會工作而且運行良好,但會不小心導致你的VS2005套用依賴於.NET3.5。運行這個批檔案會改變新的System.Web.Exteio.dll程式集的版本綁定政策,確保你只在你明確構建.NET3.5項目時才使用新的.NET3.5A.NETAJAX版本。
2)假如你曾經在你的機器上安裝過Orcas或VS2008的早期版本(Beta1或某個CTP版本)的話,你需要在安裝Beta2後重新設定你的VS2008設定。如果你不這么做的話,有些設定會非常奇怪(一些視窗在出現在奇怪的地方),你也有可能看到一些IDE性能問題。你可以在命令行上對VS2008的IDE版本鍵入“DevEnv/resetsettings”來重新設定你的配置。

控制項

.NET標準控制項根據其套用環境分為兩類:
WindowsForm控制項:主要用於Windows應用程式的開發。所有的Windows控制項都是從Control類中派生來的,該類包含了所有用戶界面的WindowsForm組件,其中也包括Form類。Control類中包括了很多位所有控制項所共享的屬性、時間和方法。它包含複選框、文本框、按鈕、標籤、圖像列表等。
Web窗體控制項:主要用於Web應用程式的開發。它是專門針對Asp.NETWeb窗體設計的伺服器控制項。Web窗體控制項包含在命名空間System.Web.UI.WebControls中,當用戶使用VisualStudio創建Web窗體頁面時,會自動在後台代碼檔案中添加引用該命名空間的Using語句。
.NETCompactFramework提供了可以滿足大多數設備項目需要的WindowsForm控制項。若要使用這些控制項沒有的功能,可以從公共控制項派生您自己的自定義控制項。可以通過定義從Control類或從程式集中的現有UserControl繼承的公共類型創建自定義控制項。
最簡單的控制項自定義是重寫公共控制項的方法。例如,可以重寫TextBox控制項的OnKeyPress繼承方法,提供將輸入限制為數字字元的代碼。
如若覺得自定義控制項過於浪費時間和複雜,也可以從受信任的來源下載控制項,並通過添加引用來導入自定義控制項。支持這些自定義的.NET的控制項有:ComponentOneStudio,Spread,ActiveReports、MultiRow等。

加密處理

信息安全是計算機套用的首要問題之一,但關於.NET加密功能的範例卻少之又少。有鑒於此,本文探討了在.NET平台下加密/解密檔案的一般過程,並提供了一個加密/解密檔案的工具。
Web服務以不容置疑的態勢迅速發展,促使許多單位開始考慮.NET之類的開發平台。但是,出於對安全問題的擔心,一些單位總是對採用新技術心存顧慮。好在有許多成熟的安全和網路技術,例如虛擬私有網路(VPN)和防火牆等,能夠極大地提高Web服務套用的安全和性能,讓開發者擁有選擇安全技術的自由,而不是非得使用尚在發展之中的XML安全技術不可。
雖然安全是信息系統的首要問題,但有關.NET安全和加密工具的範例卻少之又少。看看大多數.NET書籍的目錄,找不到任何有關安全的題目,更不用說關於密碼系統的探討了。
有鑒於此,本文將介紹如何在VB開發中運用.NET的加密和密鑰生成類,提供一個可用來加密和解密檔案的工具Cryption。有了這個工具,你就可以在硬碟上保存各種機密檔案,例如所有的密碼/用戶名字信息、收支檔案、以及其他想要保密的信息,還可以加密那些通過Internet傳送的檔案。加密技術的用途非常廣泛,你可以進一步定製本文提供的工具滿足某些特殊需要,例如增加批處理能力等。

安全威脅

攻擊和泄密是計算機面臨的兩大安全威脅。攻擊可能來自病毒,例如它會刪除檔案、降低機器運行速度或引發其它安全問題。相比之下,泄密往往要隱蔽得多,它侵害的是你的隱私:未經授權訪問硬碟檔案,截取通過Internet傳送的郵件,等等。泄密還可能伴隨著攻擊,例如修改機密檔案等。
針對泄密的最佳防範措施就是加密。有效的加密不僅杜絕了泄密,而且還防範了由泄密引發的攻擊。加密技術有時還用於通信過程中的身份驗證——如果某個用戶知道密碼,那么他應該就是那個擁有這一身份的人。
然而必須說明的是,沒有一種防範泄密的安全技術是絕對堅固的,因為密碼有可能被未經授權的人獲得。

加密前提

首先,要想使用.NET的安全功能,就必須用Imports語句引入加密用的包。試驗本文涉及的任何代碼之前,請在VB代碼視窗的頂部加入下列Imports語句:
ImportsSystem
ImportsSystem.Text
ImportsSystem.Security.Cryptography
第二,美國政府過去限制某些加密技術出口。雖然這些限制不再有效,.NET框架在Windows的出口版本中禁用了“高級”加密技術。如果你的Windows不帶高級加密能力,可以從微軟網站下載更新包:對於Windows2000,安裝ServicePack2包含的HighEncryptionPack;對於NT,安裝ServicePack6a。對於WindowsME、95、98的用戶,IE5.5也包含了HighEncryptionPack。

工具概況

本文提供的工具可用來加密和解密檔案,如果你急著給一些檔案加密,只需直接啟動本文後面提供的工具即可。
這個工具提供了一個用來輸入檔案名稱字的文本框和一個輸入密鑰的文本框,通過便捷的用戶界面提供加密、解密和密鑰生成功能。在圖一中,上方的文本框用來輸入待加密/解密檔案的名字;下面的文本框用來輸入8個字元的密碼。執行加密操作之後將生成一個新的檔案,這個經過加密的檔案和原始檔案在同一目錄下,檔案名稱字也和原始檔案的一樣,但加上了“xx”後綴,例如,假設原始檔案是MyFile.txt,則加密得到的檔案是MyFilexx.txt。
加密好之後,原始檔案不一定非刪除不可,但一般來說最好刪除,因為加密的根本目的就是為了隱藏原始檔案的數據。如果要從加密後的檔案恢復出原始檔案,在上面的文本框中輸入MyFilexx.txt,然後提供密碼,Cryption工具將創建一個與原始檔案一樣的MyFile.txt檔案。也就是說,Cryption把檔案名稱字後面的“xx”看作是要求解密密文的標誌。
注意:加密檔案之後如果忘記了用來加密該檔案的密碼,再想恢復出原始檔案就不可能了。當然,這與密碼本身的複雜程度有關,要想保證檔案的安全,最好採用較複雜的密碼,例如混合運用字母、數字和特殊字元(如“$”符號等)。
.NET提供的加密技術不止一種,不過本文討論的主要是對稱加密。對稱加密也稱為私有密鑰加密,它的特點是加密和解密用的是同一個密鑰(實際上是同一種算法),解密方和加密方都有責任保障密碼的安全(對於公用密鑰、不對稱加密,密鑰一共有兩個,其中一個密鑰是公開的,這是當前公認最有效的加密技術,但就速度而言要比對稱加密算法慢不少)。
在正式利用.NET加密類加密檔案之前,首先必須從用戶提供的密碼生成一個密鑰。密鑰可以利用Hash函式生成,Hash函式把用戶的密碼字元串轉換成一組類似隨機數序列的、無意義的數據,這組數據可作為密鑰使用,在加密過程中對原始數據進行唯一性變形處理。
例如,用密鑰加密數據的一種辦法是把原始數據的ASCII碼加上密鑰的ASCII碼:
密鑰:ab=ASCII:97,98
數據:merry=ASCII:109,101,114,114,121
把這組數據的ASCII碼加上密鑰的ASCII碼(必要時重複使用密鑰),得到的加密結果是:
9798979897
+109+101+114+114+121
206199211212218
對於同樣的數據,Hash算法總是生成同樣的結果(這就是說,對於同一個密碼,同一Hash算法總是生成相同的bit序列)。實際上,在本文提供的代碼中,利用.NET的SHA1CryptoServiceProvider類的ComputeHash方法可以驗證這一點,例如,對於同一個輸入參數morph,任何時候該方法總是返回下面的結果:124,230,93,253,197,206,136,72。因此,如果有人知道密碼以及生成密鑰的算法,他也可以輕鬆地推算出密鑰。

加密/解密

.NET加密技術要求密鑰有確定的長度,例如,DES(DataEncryptionStandard)函式要求密鑰的長度是64位,Rijndael則要求128、192或256位長度的密鑰。密鑰越長,加密強度越高。對於DES之外的加密算法,查詢LegalKeySizes屬性即可得到它允許的密鑰長度,包括MinSize(支持的最小密鑰長度)、MaxSize(最大密鑰長度)、SkipSize(增量)。SkipSize表示密鑰最大長度和最小長度之間可用長度的間隔,例如,Rijndael算法的SkipSize值是64位。
利用下面的代碼可以得到密鑰的長度信息:
'創建DES加密對象
DimdesAsNewDESCryptoServiceProvider()
Dimfd()AsKeySizes
fd=des.LegalKeySizes()'tellsusthesize(s),inbits
MsgBox("加密類型="&des.ToString()&Chr(13)&"minsize="&fd(0).MinSize&Chr(13)&_
"maxsize="&fd(0).MaxSize&Chr(13)&"skipsize="&fd(0).SkipSize)
運行上面的代碼,得到的結果是64、64、0。如果把加密對象的聲明改成TripleDESCryptoServiceProvider(),得到的結果是128、192、64。
說明:DES算法要求輸入一個8位元組的密碼,但實際使用的密鑰只有56位(7個位元組),每一個位元組的最後一位不用(它作為校驗位使用,但不用於實際的加密過程)。
下面的代碼開始生成本文示例程式的密鑰:
PublicClassForm1
InheritsSystem.Windows.Forms.Form
'保存密鑰的8位元組的數組
PrivateTheKey(7)AsByte
'在向量中放入一些隨機數據
PrivateVector()AsByte={&H12,&H44,&H16,&HEE,&H88,&H15,&HDD,&H41}
首先,代碼定義了保存密鑰和初始向量(請參見稍後的詳細說明)的兩個變數。向量的初值這裡用隨機數據填充,當然,通過密碼和Hash算法也可以獲得向量的初值。下面的過程從用戶輸入的密碼創建出密鑰:
SubCreateKey(ByValstrKeyAsString)
'保存密鑰的位元組數組
DimarrByte(7)AsByte
DimAscEncodAsNewASCIIEncoding()
DimiAsInteger=0
AscEncod.GetBytes(strKey,i,strKey.Length,arrByte,i)
'獲得密碼的Hash值
DimhashShaAsNewSHA1CryptoServiceProvider()
DimarrHash()AsByte=hashSha.ComputeHash(arrByte)
'將Hash值保存到密鑰
Fori=0To7
TheKey(i)=arrHash(i)
Nexti
EndSub
用戶的密碼(strKey)傳入到CreateKey過程,分解成一組ASCII值保存到一個位元組數組。把這個位元組數組傳遞給SHA1CryptoServiceProvider類的ComputeHash方法,返回一個Hash值。把這個Hash值保存到TheKey數組,供以後的加密/解密過程使用(注意SHA1CryptoServiceProvider實際能夠支持160位,但本文示例程式只用到64位)。
那么,初始向量究竟起什麼作用呢?這個位元組數組有8個元素,就象密鑰一樣,但向量和密鑰的作用是不同的,向量用來避免DES之類的算法一個特有的問題。在DES之類的算法中,原始數據被分成8位元組一塊然後分別處理。DES在加密一塊數據時,要用到前一塊數據的模式,也就是說,如果改動了原始數據中第一塊的某個字元,所有後繼的塊的內容都將隨之改變,從而避免了一系列相連線的塊中出現重複塊的問題。
例如,假設你一時高興,發了一個郵件,內容只有幾個重複的單詞“Melanie!Melanie!Melanie!Melanie!”,在密鑰和塊序列中前一塊的共同作用下,加密之後的密文不會出現重複現象。然而,進一步考慮這個加密過程可以發現,如果用同一個密鑰加密多個郵件,且郵件開頭的問候語都相同,則郵件開頭的一部分很容易受到攻擊。由於這個原因,我們用初始向量來模擬前一個塊。
本文加密/解密工具中的下面這段代碼示範了如何加密檔案:
SubEncrypt(ByValinNameAsString,ByValoutNameAsString)
Try
'創建緩衝區
Dimstorage(4096)AsByte
'已經寫入的位元組數量
DimtotalBytesWrittenAsLong=8
'每次寫入的位元組數量
DimpackageSizeAsInteger
'聲明檔案流
DimfinAsNewFileStream(inName,FileMode.Open,FileAccess.Read)
DimfoutAsNewFileStream(outName,FileMode.OpenOrCreate,FileAccess.Write)
fout.SetLength(0)
'源檔案的大小
DimtotalFileLengthAsLong=fin.Length
'創建加密對象
DimdesAsNewDESCryptoServiceProvider()
DimcrStreamAsNewCryptoStream(fout,_
des.CreateEncryptor(TheKey,Vector),_
CryptoStreamMode.Write)
'輸出加密後的檔案
WhiletotalBytesWritten<totalFileLength
packageSize=fin.Read(storage,0,4096)
crStream.Write(storage,0,packageSize)
totalBytesWritten=Convert.ToInt32(totalBytesWritten+_
packageSize/des.BlockSize*des.BlockSize)
EndWhile
crStream.Close()
CatcheAsException
MsgBox(e.Message)
EndTry
EndSub
注意這段代碼創建了三個檔案流:fin,表示明文形式的原始檔案;fout,加密結果檔案;crStream,加密流,用來把DES加密的結果轉入輸出檔案fout。增加一個crStream流的好處是不必把結果保存到臨時檔案或緩衝區。
加密過程與解密過程的唯一重要區別是,執行解密時,我們將使用DESCryptoServiceProvider對象的另一個方法CreateDecryptor,除此之外,兩者其餘的處理步驟(包括參數,檔案流,等等)基本相同。

防止破解

黑客和密碼專家破解加密檔案的辦法主要有兩個,第一是搜尋密文是否有重複現象,第二是用暴力破解法獲得密鑰。首先我們考慮一下初始向量如何防止重複現象,然後再探討一下防止暴力破解的關鍵問題。
破解密文的第一種方式是搜尋樣本——特別是重複的樣本。人們在寫信的時候總是喜歡用同樣的文字開頭,例如“親愛的XXX”、“DearSir”等,如果多個郵件的開頭文字相同且通過同一密鑰加密,則每個密文信件的開頭也相同。假設Antonio寫給Melanie的所有加密信件都有相同的問候語“@4^F(2$@Fx”,解密者就會首先檢查開頭的幾個單詞是不是“DearMelanie”。解密機密檔案的一個重要步驟就是猜測檔案中應當會出現的幾個單詞,所以我們不應該給解密者提供這種方便。在本文的示例中,初始向量的內容被附加到檔案的開頭,從而防止了出現重複現象。只有信件的開頭才容易受到此類攻擊。
計算機的運算速度和精度要遠遠超過人,特別擅長處理一些重複的任務,例如嘗試每一種可能的密鑰組合最終破解密鑰。DES加密算法本身是不安全的,這種加密算法早在70年代就已經公之於眾。而且,破解者如果想要讓搜尋密鑰的過程自動化,同樣可以方便地運用.NET的DESCryptoServiceProvider類。
對於一個128位、結合運用密鑰/初始向量的加密方案,計算機嘗試每一種可能的密鑰組合要花多少時間?專家們的看法並不一致,有人認為需要數月,也有人認為裝有專用硬體的價值6位數的計算機每秒能夠驗證數十億個密鑰,破解DES密文只需數小時。如果你的機密值得花數月時間去破解,那么最好改用TripleDES或其他加密算法。從TripleDES的名字也可以猜出,這種加密方式採用三重數據加密標準算法,所以密鑰的長度是192位,而不是64位的DES密鑰。記住,在其他條件相同的情況下,密鑰越長,安全程度越高。
結束語:現在你已經了解了.NETDES加密算法的使用過程,接下去可以研究.NET的其他安全功能,包括極具吸引力的公用密鑰加密方案。雖然公用密鑰加密方案執行起來速度慢一些,但加密效果一般要比TripleDES好。

未來發展

預測未來,在技術世界是常有的事兒。從高級語言的發展歷史來看,編程世界從來就沒有停止過腳步,變革時時發生、創新處處存在。以技術人員的角度來觀摩未來,帶著C#4.0的腳步來看展望,除了在函式式編程、並行計算和動態特性上大展拳腳,MetaProgramming的概念已然浮出水面,將編譯器變成一個Service,你可以自由控制在編譯器和運行期的邏輯,那是多么美好而嚮往的未來呀,所以,我們堅信4.0之後還有廣闊的天地隨著語言的變遷變得更加開闊。
概括Anders大師在C#設計過程中的思想,C#是語言美學的集大成者。例如,當使用foreach進行循環遍歷之後,當套用using語句代替try/finally實現強制資源管理,當應該attribute進行運行時反射,當以LINQ進行語言級別的信息查詢,這些語言級別的支持為C#實現面向對象編程帶來強大的功能動力和美學感受。

書籍

C#程式設計
C#Primer中文版
.NET框架程式設計(修訂版)
c#Windows程式設計
.NET程式設計技術內幕
.NET本質論--第1卷:公共語言運行庫(中文版)

註冊規則

1、只提供英文字母(a-z,不區分大小寫)、數字(0-9)、以及"-"(英文中的連詞號,即中橫線),不能使用空格及特殊字元(如!、$、&、?等)。
2、"-"不能用作開頭和結尾。
3、長度不能超過63個字元。
4、簡單、易記,邏輯性強(與企業商標、產品名稱吻合;根據網站的性質、用途選擇)。
5、為同一個域名註冊多個不同後綴。
6、域名購買年限選擇2年以上。

注意問題

1、域名安全與產權方面來說:一定要正確填寫域名的所有人(這項非常重要,是關係到域名的產權問題及以後的域名過戶、轉移註冊商等問題)、註冊聯繫人及身份證、管理聯繫信箱(信箱必須是經常使用的,以便續費的時收到提醒通知);如果註冊信息發生變化,應當及時更新。
2、域名註冊時候最好選擇好用、易記的域名,以便於宣傳和推廣。
3、注意全方位保護自己的域名品牌,現在網際網路上域名已經成為寶貴的域名資源,如果你註冊了一個域名之後,最好將相關的域名也註冊下來,以避免被別人搶注。例如註冊了.com域名,可以同時將.net、.cn、.com.cn、.net、.cn、.info等這些域名同時保護起來。適當的時候要考慮將一些類似的域名也註冊掉。
4、除了傳統的.cn、.com、.net等純英文域名後綴之外,還有以“.中國”結尾的純中文域名,並且註冊“中文.CN”將自動獲得對應的“中文.中國”域名,獲贈繁體中文,無需另行申請註冊。
對於企業用戶,最好還要註冊自己的中文域名,做到面面俱全,以鎖定自己在網際網路上絕對安全和品牌壟斷權。
5、為避免域名過期導致要高價贖回,或是被搶注而要付出高成本代價,或是解析暫停影響網站訪問的情況,按時續費也是非常重要的。所有域名過期後30天內可正常續費。

熱門詞條

聯絡我們