分享人:傅云
特邀嘉賓: 周振濤
原文出處: 鏈接:https://bbs.kafan.cn/thread-2073476-1-1.html
1. 前言
經(jīng)常有人這樣問,“電腦中的.NET Framework是什么,可以卸載嗎?”,“.NET Framework會(huì)拖慢系統(tǒng)速度嗎?”,“有.NET4.5需要安裝.NET3.5嗎?”。
如果你是一個(gè).NET編程新手(尤其是沒有任何編程基礎(chǔ)的),初次看到.NET的諸多術(shù)語,如CLR,CIL,JIT,程序集等概念,可能會(huì)覺得很混亂,而剛?cè)腴T去理解MSDN比較困難。
本文將盡力以淺顯易懂的方式整理.NET Framework相關(guān)內(nèi)容和技術(shù)的關(guān)系。
樓主不是程序媛,也是小白級(jí)別的,內(nèi)容僅供參考,若有錯(cuò)誤歡迎討論。希望本文能幫到大家。
2. .NET Framework概述
.NET(讀作“DotNet”) Framework是Microsoft為開發(fā)和運(yùn)行程序而建立的一個(gè)平臺(tái)(應(yīng)用程序包括桌面應(yīng)用程序,Windows Store應(yīng)用程序,Web應(yīng)用程序等)。我們平常所說的.NET指的就是.NET Frakework。但.NET Framework其實(shí)是微軟.NET戰(zhàn)略目前最重要的實(shí)現(xiàn)而已。
.NET 是具有多種實(shí)現(xiàn)(.NET Framework、Mono、Unity .NET Core)的 ECMA 標(biāo)準(zhǔn)。
Microsoft力求實(shí)現(xiàn).NET的平臺(tái)無關(guān)性(“無關(guān)性”指在.NET上開發(fā)的的程序可以跨平臺(tái)運(yùn)行。“平臺(tái)”指的是各個(gè)系統(tǒng)環(huán)境,如Linux)。本文只介紹.NET Framework,它相對(duì)最重要也使用最廣泛。
應(yīng)用程序總是要轉(zhuǎn)為二進(jìn)制代碼才能運(yùn)行。在有.NET平臺(tái)之前,Windows程序是一般是直接運(yùn)行在Windows上的,這種應(yīng)用程序內(nèi)包含的是本機(jī)代碼(二進(jìn)制代碼),而之后,.NET應(yīng)用中包含的是一種CPU不能直接解析的中間代碼,只有.NET Framework中的JIT(及時(shí)編譯器,下文介紹)才可以把它實(shí)時(shí)的編譯成本機(jī)代碼運(yùn)行。所以下圖這種彈窗已經(jīng)可以簡單解釋了,運(yùn)行.NET應(yīng)用需要.NET執(zhí)行環(huán)境。
.NET Framework主要有兩個(gè)組件,一個(gè)是.NET Framework類庫,另一個(gè)是CLR(公共語言運(yùn)行時(shí))。(暫時(shí)不用理解,下文介紹)
3. .NET類庫
在編寫程序中,一些經(jīng)常使用的功能,如最簡單的求三角函數(shù)值,復(fù)雜一點(diǎn)的如創(chuàng)建一個(gè)窗體等,如果讓程序員編寫來實(shí)現(xiàn)這些是很麻煩的。比如計(jì)算6/π的正弦值,(現(xiàn)在只需注意紅色部分):
紅色部分即調(diào)用了.NET 類庫中一個(gè)求正弦值的函數(shù),如果類庫中沒有這個(gè)函數(shù)計(jì)算三角函數(shù)呢?至少實(shí)現(xiàn)求任意弧度的三角函數(shù)值對(duì)我來說是很復(fù)雜的事情。
當(dāng)然如果.NET類庫只包含這些簡單的功能,也沒什么大用。.NET Framework類庫叫Framework Class Library(FCL),它封裝了很多高級(jí)的功能,比如我們常見的Windows窗體的代碼,WPF,ASP.NET等。而Base Class Library(BCL)是FCL的一個(gè)子集,它包含了一些十分基礎(chǔ)的東西,如一些類型,向屏幕上輸出一句話,計(jì)算某個(gè)數(shù)的絕對(duì)值等。
如果不調(diào)用FCL中的一些封裝的功能,同樣會(huì)讓開發(fā)時(shí)間變得很長。如果想在程序中彈出一個(gè)消息框,(如右圖)
只需要輸入System.Windows.Forms.MessageBox.Show("Hello , C# World!","Howdy","MessageBoxButtons.OK",MessageBoxIcon.Information);
即可。
如果FCL中沒有這個(gè)功能,那就需要調(diào)用系統(tǒng)相關(guān)Windows API,顯然比較麻煩。而下面的這個(gè)示例只是最簡單的調(diào)用。
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("User32.dll")]
public static extern int MessageBox(int a, string b, string c, int type);
static void Main()
{
MessageBox(0, "Hello , C# World !", "Howdy", 4);
Console.ReadKey(true);
}
}
什么是Windows API(這里給出一種簡單的理解,不十分準(zhǔn)確):Windows提供了很多操控Windows本身的接口,編程人員需要通過這些接口使用系統(tǒng)的一些功能,這些接口就是API。
讀到這里,有些童鞋可能要問了,庫很好理解,“類”是什么意思?按照類庫的一般定義:
類庫(Class Library)是一個(gè)綜合性的面向?qū)ο蟮目芍赜妙愋图希@些類型包括:接口、抽象類和具體類。
下面簡要介紹僅“面向?qū)ο蟆保唤榻B接口和抽象類,這樣“類”就很好理解了。(不懂編程也可以看)
*為什么要講面向?qū)ο螅恳驗(yàn)?NET Framework類庫中大都遵循“面向?qū)ο蟆痹O(shè)計(jì),不然你只會(huì)簡單的認(rèn)為它是個(gè)“庫”。以及為后文做鋪墊。
在生活中,每一個(gè)實(shí)物都可以看作一個(gè)“對(duì)象”,而將某一種對(duì)象的特征(包括行為特征和靜態(tài)特征)提取出來,形成一個(gè)“模板”,這個(gè)“模板”就是我們所說的“類”,“類”僅僅是描述了“對(duì)象”的特征,并不實(shí)際存在。如果“人類”是一個(gè)模板,那么身高,體重,性別就可以看做是模板中定義的靜態(tài)特征,而“走路”是動(dòng)態(tài)特征。依照這個(gè)模板有一個(gè)人,身高為“165”,體重為“55kg”,性別為“女“,此時(shí)這個(gè)人就是一個(gè)對(duì)象,就可以使她的動(dòng)態(tài)特征(走路)表現(xiàn)出來。在面向?qū)ο蟮男g(shù)語中,“動(dòng)態(tài)特征”叫做“方法”。要點(diǎn):“類”是抽象模板,對(duì)象是實(shí)體,對(duì)象能做的事叫“方法”。
這里的“模板”指的是生活中的“模板”,不是C++中的“模板”。
在.NET類庫中,很多功能被封裝成“類”的形式,只需要將“類”實(shí)例化稱對(duì)象,就可以讓“對(duì)象”做一些事情。面向?qū)ο蟮某绦蛟O(shè)計(jì),就是讓程序由多個(gè)“對(duì)象”組成,并讓這些對(duì)象互相交互。如下所示,.NET Framework類庫中提供了一個(gè)FileSystemWatcher類(用以監(jiān)控文件及文件夾的變化),將其實(shí)例化成“對(duì)象”并監(jiān)控指定的目錄(這里是C盤),目前并不需要看懂它,這里的目的是為了讓讀者了解.NET Framework類庫中類的作用。
[mw_shl_code=xml,true]using System;
using System.IO;
namespace test
{
class Program
{
static void Main(string[] args)
{
Program.WatcherStart(@"C:\", "*.txt");
//監(jiān)控C盤
Console.ReadKey();
}
private static void WatcherStart(string path, string filter)
{
FileSystemWatcher watcher = new FileSystemWatcher();//將.NET類庫中的FileSystemWatcher類實(shí)例化
watcher.Path = path;
watcher.Filter = filter;//將類中某些“抽象特征”賦予真實(shí)的值。
watcher.Changed += new FileSystemEventHandler(OnProcess);
watcher.Created += new FileSystemEventHandler(OnProcess);
watcher.Deleted += new FileSystemEventHandler(OnProcess);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
watcher.EnableRaisingEvents = true;
}
private static void OnProcess(object source, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Created)
{
OnCreated(source, e);
}
else if (e.ChangeType == WatcherChangeTypes.Changed)
{
OnChanged(source, e);
}
else if (e.ChangeType == WatcherChangeTypes.Deleted)
{
OnDeleted(source, e);
}
}
private static void OnCreated(object source, FileSystemEventArgs e)
{
Console.WriteLine(e.FullPath+"被創(chuàng)建");
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
Console.WriteLine(e.FullPath+"發(fā)生變化");
}
private static void OnDeleted(object source, FileSystemEventArgs e)
{
Console.WriteLine(e.FullPath+"被刪除");
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
Console.WriteLine(e.FullPath+"被重命名");
}
}
}
[/mw_shl_code]
看到這里,應(yīng)該感覺到.NET類庫的強(qiáng)大了,監(jiān)控一個(gè)文件夾需要調(diào)動(dòng)很多Windows API,而現(xiàn)在.NET Framework類庫提供了一個(gè)模板,即“類”,通過實(shí)例化FileSystemWatcher這個(gè)類產(chǎn)生一個(gè)對(duì)象就可以調(diào)用這個(gè)對(duì)象的“方法”監(jiān)控文件夾了,至于這個(gè)對(duì)象內(nèi)部構(gòu)造并不清楚,就像你讓我走路,你肯定不會(huì)去考慮我身體內(nèi)三磷酸腺苷與二磷酸腺苷之間的轉(zhuǎn)換之類的東西,直接讓我這個(gè)“對(duì)象”去走路即可。(這里多嘴一句,這個(gè)監(jiān)控功能滿足一般需要,像殺軟那樣嚴(yán)密的監(jiān)控不是這樣來的)。在編程中,你可以選取不同的類,將它們實(shí)例化成“對(duì)象”。編寫出強(qiáng)大的程序。
這2點(diǎn)作了解:
由于程序是由各個(gè)對(duì)象組成,因此維護(hù)和糾錯(cuò)變得比較容易,在編寫程序前只需要考慮程序由哪些對(duì)象構(gòu)成,處理對(duì)象之間交互的邏輯問題即可。
“不清楚內(nèi)部構(gòu)造”體現(xiàn)了面向?qū)ο蟮摹胺庋b性”,.NET類庫中的很多類也是如此,并不能直接看出它是怎么實(shí)現(xiàn)相關(guān)功能的。
4. .NET程序的編譯和運(yùn)行
4.1 CIL
CIL(Common Intermediate Language),即通用中間語言,和MSIL(Microsoft Intermediate Language ),IL(Intermediate Language )都是一回事,不要被它們攪昏了,只是在.NET的測(cè)試版中被稱為MSIL,后來官方改稱CIL,但很多人都習(xí)慣叫它MSIL。
一個(gè).NET程序被人用代碼寫出來后,不是被編譯器“翻譯”成計(jì)算機(jī)能識(shí)別的二進(jìn)制指令,而是形成CIL。寫一個(gè)簡單的“Hello World!"小程序如下,這些代碼是人寫出來的,需要編譯器把它翻譯成CIL:
[mw_shl_code=xml,true]
using System;
class Program
{
static void Main(string[] args)
{
string hello = "Hello World";
Console.WriteLine(hello);
Console.Read();
}
}[/mw_shl_code]
然后編譯器翻譯成這樣(看上去有點(diǎn)匯編的風(fēng)格):
為什么要翻譯成中間語言而不是直接二進(jìn)制代碼呢,這樣不是多此一舉嗎?并不是。
二進(jìn)制代碼與平臺(tái)有關(guān),在這個(gè)平臺(tái)上可以執(zhí)行,在另一個(gè)上面不一定,不是一份代碼直接拷來拷去到處都可以執(zhí)行。而理論上講,CIL因?yàn)榕c.NET平臺(tái)相關(guān)聯(lián),是由.NET Framework中的JIT進(jìn)行編譯成適合.NET Framework所在框架的平臺(tái)的二進(jìn)制代碼,因此一份代碼可以“一次編譯,到處使用”,減少了程序員的負(fù)擔(dān),平臺(tái)兼不兼容.NET程序,取決于.NET Framework與平臺(tái)的兼容性,這不該由程序員考慮。但就如上文所說,.NET Framework主要還是運(yùn)行在Windows平臺(tái)之上,針對(duì)其他平臺(tái)的.NET Framework還未成熟。
如果沒有.NET Framework,程序員為了讓程序在不同平臺(tái)運(yùn)行,需要這樣做:
有了.NET Framework,可以簡化開發(fā)(按照理論來講,實(shí)際中并不是):
是什么能讓編譯器將高級(jí)語言轉(zhuǎn)為CIL呢?當(dāng)然是程序員需要使用.NET Framework支持的語言了,比如C#,F(xiàn)#等(后文簡單介紹),這些語言的編譯器可以把人寫的語句轉(zhuǎn)為CIL。(當(dāng)然你愿意直接寫CIL代碼也行,但這樣很容易出錯(cuò),而且大多數(shù)情況下根本不需要)
4.2 及時(shí)編譯器JIT
再次強(qiáng)調(diào),CIL代碼不能直接執(zhí)行!這時(shí)需要.NET Framework中的JIT編譯器發(fā)揮作用了。運(yùn)行一個(gè).NET程序后,JIT編譯器會(huì)立刻翻譯一些需要的代碼,而不是把所有代碼一次性都翻譯成本機(jī)代碼,在運(yùn)行時(shí)也是這樣。(這也是為什么叫它及時(shí)編譯器)
在Windows平臺(tái)中,CLR(后文介紹CLR)帶有三個(gè)不同的JIT編譯器:
- 缺省的編譯器---主編譯器,由它進(jìn)行數(shù)據(jù)流分析并輸出經(jīng)過優(yōu)化的本地代碼,所有的中間代碼指令均可被它處理。
- PREJIT,它建立在主JIT編譯器之上。每一個(gè).NET組件安裝時(shí)它開始運(yùn)行。
- ECONOJIT,在并不充分優(yōu)化代碼的前提下,它能夠快速完成IL代碼到本地碼的轉(zhuǎn)換,編譯速度與運(yùn)行速度都非常快。
什么是代碼優(yōu)化?比如你有一個(gè)翻譯幫助你和英國人說話,你說“今天......那個(gè)......那個(gè).......我沒有......吃飯”,你的翻譯如果沒有“優(yōu)化”你的話,就會(huì)說成“Today...Err...Err...I did not... eat."雖然意思是表達(dá)清楚了,但一點(diǎn)也不好聽還浪費(fèi)時(shí)間,如果翻譯“優(yōu)化”你的話,就會(huì)說成“I did not eat today!",這樣就清楚多了。
在ECONOJIT中,它是逐條地將CIL代碼轉(zhuǎn)譯為本機(jī)代碼,速度是很快,但代碼并不會(huì)怎么優(yōu)化。
舉個(gè)簡單的優(yōu)化代碼的例子,但JIT的優(yōu)化規(guī)則很復(fù)雜,怎么優(yōu)化實(shí)際上我并不清楚,以下只是個(gè)示例(選看):
[mw_shl_code=css,true]public void GetResult(out int properNumber, out int scoreSum)
{
try
{
properNumber = 0;
char[] chArray = this.readAnswers.ToCharArray();
char[] chArray2 = standardAnswers.ToCharArray();
for (int i = 0; (i < chArray.Length) && (i < chArray2.Length); i++)
{
properNumber = (chArray == chArray2) ? (properNumber + 1) : properNumber;
}
scoreSum = this.subjectiveQuestionScore + (properNumber * scorePerOneQuestion);
}
catch (NullReferenceException exp)
{
MessageBox.Show("未設(shè)置標(biāo)準(zhǔn)答案或分值", "輸入錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
properNumber = 0;
scoreSum = 0;
}
}
[/mw_shl_code]
實(shí)際上catch (NullReferenceException exp)中exp這個(gè)引用(在棧內(nèi)存中)并沒有(這里簡單理解為,按照代碼,應(yīng)該分配一點(diǎn)內(nèi)存,但實(shí)際上并沒有,因?yàn)椴恍枰驗(yàn)槲覜]有exp使用這個(gè)變量。實(shí)際效果是catch (NullReferenceException)。改變catch子句為:
[mw_shl_code=shell,true]catch (NullReferenceException exp)
{
System.Diagnostics.Trace.WriteLine(exp.ToString());
MessageBox.Show("未設(shè)置標(biāo)準(zhǔn)答案或分值", "輸入錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
properNumber = 0;
scoreSum = 0;
}
[/mw_shl_code]
這樣使用了exp這個(gè)變量。效果如catch (NullReferenceException exp)。
而像傳統(tǒng)的C++編譯器,是編譯程序員寫的代碼時(shí)將其優(yōu)化并轉(zhuǎn)成本機(jī)代碼,執(zhí)行的時(shí)候,直接執(zhí)行這個(gè)二進(jìn)制代碼。而使用JIT不同,它是用戶要運(yùn)行的時(shí)候才去實(shí)時(shí)的編譯成本機(jī)代碼,執(zhí)行過一次的本機(jī)代碼會(huì)緩存。有些童鞋可能會(huì)覺得這樣可能影響性能,但是(僅是理論上)JIT將CIL編譯成本機(jī)代碼時(shí)是針對(duì)本機(jī)硬件的特性做了優(yōu)化的,針對(duì)性更強(qiáng),而傳統(tǒng)的直接生成的本機(jī)代碼為了考慮兼容性不得不使用基本的指令集而可能無法發(fā)揮硬件的性能,但是JIT將CIL轉(zhuǎn)為本機(jī)代碼可能會(huì)花費(fèi)一點(diǎn)時(shí)間。但實(shí)際中來看,兩者差別不是很大。
4.3 程序集
按照一般的定義,程序集是:
程序集(assembly)是包含編譯好的、面向.NET Framework的代碼的邏輯單元
它的意思就是,.NET程序的文件就叫做程序集,包括打包進(jìn)去的圖片,音樂等,都屬于程序集的一部分,但它準(zhǔn)確地講是一個(gè)邏輯單元,動(dòng)態(tài)程序集存儲(chǔ)在內(nèi)存中,而不是存儲(chǔ)在文件中。比如我在程序中調(diào)用了一個(gè)kernel32.dll,顯然不會(huì)把它打包到程序文件里去,但我使用了它,它就可算作程序集的一部分。一般Windows平臺(tái)上的程序集由以下及部分組成:
- [mw_shl_code=css,true]PE文件頭
- CLR(下文介紹)文件頭
- CIL代碼
- 元數(shù)據(jù)(metadata)
- 程序集清單(manifest)
- 可選的嵌入資源
- [/mw_shl_code]
在Windows上的程序集后綴名一般是.exe或者.dll,但僅僅是后綴名和其他程序一樣,其內(nèi)部是不同的。看著個(gè).NET程序,如果我不告訴你這是.NET程序,單憑后綴名是exe或dll無法判斷。
當(dāng)然其他平臺(tái)的程序集一般不會(huì)有PE文件頭。任何一個(gè)可直接或間接執(zhí)行的文件,要想讓W(xué)indows執(zhí)行,必須告訴一聲Winsows“我是可以被執(zhí)行的”,然后由Windows再調(diào)用CLR來執(zhí)行,而不會(huì)由CLR直接檢測(cè)到你的雙擊文件而運(yùn)行.NET程序。
CLR文件頭,就表明這個(gè)文件需要CLR(去執(zhí)行)。
程序集清單,其包含的信息是程序集內(nèi)的各個(gè)部分之間的關(guān)系,還有上圖屬性中的語言,地區(qū),版本號(hào)之類也在這里面。metadata暫不介紹。
嵌入資源,比如圖片之類的就是這一種。
4.4 CLR
CLR,公共語言運(yùn)行時(shí),指的就是執(zhí)行.NET程序的這個(gè)大環(huán)境,包含有JIT編譯器,它負(fù)責(zé).NET程序的內(nèi)存管理(.NET程序是由CLR管理內(nèi)存使用的),程序集(參見上文)加載,異常處理,線程同步(這兩點(diǎn)本文不會(huì)介紹,超出了范圍)等。(在CLR上執(zhí)行的代碼一般是托管代碼,即上文一直提到的代碼,但CLR可以執(zhí)行一些非托管代碼)。
知識(shí)回顧:.NET Framework由兩大模塊組成,其一是類庫,另一個(gè)是CLR(運(yùn)行環(huán)境)。
托管代碼的一大特性就是內(nèi)存由CLR管理,不可能手動(dòng)顯式摧毀一個(gè)“對(duì)象”(上文已經(jīng)介紹“對(duì)象”),當(dāng)對(duì)象不再使用時(shí),.NET CLR的垃圾回收器會(huì)擇機(jī)刪除它。如下面的例子為了好說明,用new運(yùn)算符初始化string對(duì)象,在.NET中,為對(duì)象分配的內(nèi)存叫“堆”(選看):
using System;
class Test
{
static void Main()
{
string myStr = new string();
myStr = null;//去除引用
}
}
即使myStr不再指向新的string對(duì)象,雖然這個(gè)對(duì)象肯定沒有用了,但也不能保證馬上被回收。如果加一句GC.Collect();,能夠觸發(fā)垃圾回收器,但垃圾回收器什么時(shí)候運(yùn)行,運(yùn)行時(shí)是否清理對(duì)象,均無法預(yù)判。更多的垃圾回收器的細(xì)節(jié),這里不再多講。
不能手動(dòng)摧毀對(duì)象不代表不能釋放對(duì)象占的非托管資源。
5.CLS和CTS
也許這兩個(gè)概念剛開始很難搞清楚。這里簡單的理清思路。
可以生成CIL代碼的語言很多(即.NET平臺(tái)上的語言),比如C#,F(xiàn)#,VB等,而.NET平臺(tái)的目的之一就是語言的互操作性,不管是.NET上的什么語言,都被編譯器生成CIL。如果各個(gè)語言之間的類型能夠?qū)?yīng).NET中的類型,那么語言交互便很容易了。類型是編寫程序中數(shù)據(jù)的類型。
比如在內(nèi)存中申請(qǐng)一個(gè)地址,取名為i,給這個(gè)地址所代表的空間里“裝”一個(gè)整數(shù)3,在VB的語法中是Dim i as Integer = 3 在C#中是int i = 3; VB語法中中的Integer和C#語法中的int同時(shí)映射到.NET類庫中的整數(shù)類型System.Int32。
.NET庫中定義了一套CTS(公共類型系統(tǒng)),各個(gè)語言互相交換數(shù)據(jù)時(shí)才能暢通無阻。 但是各個(gè)編程語言中不相同的可不只是類型,還有語法,有些語言中的特性在.NET Framework這個(gè)大環(huán)境中是沒有定義的,該怎么辦呢?
一般是3種方法:
- 改變語言本身(類似于.NET版本的語言,比如VB.NET):.NET版本的VB比到原來VB6上修改擴(kuò)充了很多東西,才符合了規(guī)范。
- 增加語言中的特性,但原來不相容的部分不去處理它,比如C++,托管部分編譯成托管代碼,其他部分編譯成非托管代碼。
- 第三種主要靠比較厲害的編譯器,如.NET CLR中沒有定義多繼承,(多繼承:比如有三個(gè)“類”,一個(gè)是“床”,另一個(gè)是“沙發(fā)”,還有一個(gè)是“沙發(fā)床”,則“沙發(fā)床”可以看作是繼承了“床”和“沙發(fā)”的特征,但.NET中不允許這樣,只能是單繼承,如“程序員”是“人”,“程序員”就繼承了“人”),但是有些語言中有多繼承這種語法,為了滿足CTS,又不想放棄這個(gè)特征,只好利用.NET支持的特性“繞圈子”實(shí)現(xiàn),Eiffel的編譯器就是利用Interface以及Attribute來達(dá)到多重繼承的目的。
看下面這個(gè)Venn圖(Fortran也是一種語言)),可以清楚地看出CLS是什么:
CLS制定了一種以.NET平臺(tái)為目標(biāo)的語言所必須支持的最小特征,還有該語言與其他.NET平臺(tái)的語言之間實(shí)現(xiàn)互操作所需要的特征。有了.NET,仍可以創(chuàng)建不能在不同語言中使用的組件,代碼可以不滿足CTS,但.NET平臺(tái)語言的編譯器必須支持CLS(因?yàn)樗亲钚∽蛹耍┍热缒撤N.NET平臺(tái)語言中沒有定義無符號(hào)整數(shù)。
public uint Fuc()
{
return 1;
}
這種語言調(diào)用不了上面的函數(shù),因?yàn)闆]有定義無符號(hào)整數(shù)。為了滿足互操作性,最好讓代碼遵循CLS。
總的來說,CLS是CTS的子集,.NET平臺(tái)的語言不完全支持CTS可以,但必須支持CLS。
6. .NET平臺(tái)上的語言
支持.NET平臺(tái)的語言(部分或完全支持)很多,如C#,VB.NET,F#,C++.net,Eiffel,COBOL等等,什么語言不重要,重要的是能不能由特定的編譯器把他們轉(zhuǎn)成CIL,高級(jí)語言畢竟只是人看的,但由于除C#,F(xiàn)#外這些語言大都出現(xiàn)在.NET平臺(tái)之前,所以部分.NET平臺(tái)的特性并不支持。C#,F(xiàn)#是微軟開發(fā)的,自然,C#對(duì)于.NET的各種特性支持的最好(但不是全部都支持,有些特性只能由編寫CIL實(shí)現(xiàn)。
7. .NET相關(guān)問題
-
1. .NET Framework框架版本向下兼容嗎?**
(利用不同.NET Framework生成的程序)
.NET框架不是一成不變的。.NET版本從1.0到現(xiàn)在的4.,其CLR版本號(hào)并不是1-4的,.NET4以上的CLR版本號(hào)是4.0,一般來說,在4.0以上,版本是向后兼容的(到4.0),.NET2.0~.NET3.5對(duì)應(yīng)的CLR版本號(hào)是2.0,CLR沒有3.這個(gè)版本號(hào)。這之間的.NET Framework生成的程序一般可以向后兼容到.NET2.0,.NET1.0~.NET1.1的程序已經(jīng)十分老舊,這里不做討論。CLR版本不變,主要更新的是.NET Framework的類庫。
為了運(yùn)行不同版本的.NET程序,可以安裝多個(gè)版本的.NET Framework,一般并不需要考慮裝哪個(gè)版本,如果一個(gè)程序需要其他版本的.NET Framework,會(huì)自動(dòng)提示。.NET與某些版本的Windows集成,下表僅供參考:
-
2. .NET會(huì)拖慢運(yùn)行速度嗎?
多半是百度知道上某些人的回答。.NET Framework的安裝與開機(jī)時(shí)間和運(yùn)行速度沒有必要的聯(lián)系。JIT編譯器實(shí)時(shí)編譯在某些老機(jī)器可能會(huì)慢一點(diǎn),但現(xiàn)在很難感覺到。
而且軟件的運(yùn)行速度不僅取決于運(yùn)行環(huán)境,還在于代碼的質(zhì)量。用非托管C++照樣可以寫出性能很差的程序。
-
3. .NET Framework可以卸載嗎?
系統(tǒng)集成的版本,多半卸載不了,只能把它關(guān)了,自己安裝的其他版本確認(rèn)沒有程序依賴.NET Framework也可以刪除,但不推薦。其他更多的問題,在看了本文的介紹后應(yīng)該可以理解MSDN針對(duì)用戶使用.NET Framework的問題的回答了。
地址:https://msdn.microsoft.com/zh-cn/library/w0x726c2(v=vs.110).aspx