2017.11.01 帶你走近.NET Framework

分享人:傅云
特邀嘉賓: 周振濤

原文出處: 鏈接: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概述

image.png

.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)在只需注意紅色部分):

image.png

紅色部分即調(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è)消息框,(如右圖)

image.png

只需要輸入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)作了解:

  1. 由于程序是由各個(gè)對(duì)象組成,因此維護(hù)和糾錯(cuò)變得比較容易,在編寫程序前只需要考慮程序由哪些對(duì)象構(gòu)成,處理對(duì)象之間交互的邏輯問題即可。

  2. “不清楚內(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)格):

image.png

為什么要翻譯成中間語言而不是直接二進(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)行,需要這樣做:

image.png

有了.NET Framework,可以簡化開發(fā)(按照理論來講,實(shí)際中并不是):

image.png

是什么能讓編譯器將高級(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編譯器:

  1. 缺省的編譯器---主編譯器,由它進(jìn)行數(shù)據(jù)流分析并輸出經(jīng)過優(yōu)化的本地代碼,所有的中間代碼指令均可被它處理。
  2. PREJIT,它建立在主JIT編譯器之上。每一個(gè).NET組件安裝時(shí)它開始運(yùn)行。
  3. 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無法判斷。

image.png

當(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)境)。

image.png

托管代碼的一大特性就是內(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種方法:

  1. 改變語言本身(類似于.NET版本的語言,比如VB.NET):.NET版本的VB比到原來VB6上修改擴(kuò)充了很多東西,才符合了規(guī)范。
  2. 增加語言中的特性,但原來不相容的部分不去處理它,比如C++,托管部分編譯成托管代碼,其他部分編譯成非托管代碼。
  3. 第三種主要靠比較厲害的編譯器,如.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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容