.net 基礎

以前給你們總結了java的面試幾回技巧總結,同窗們看了以爲仍是不錯,可以獲得你們的承認,感受仍是挺不錯的。如今又有同窗來想小編索要.NET面試的總結了,好吧。誰讓小編這麼好呢!如下是.NET面試之框架基礎知識html

  1 、術語java

  面試出現頻率:歷來沒人問過。事實上我都不知道怎麼問,考背書嗎?卻是能夠問問知不知道如今.NET最新版本是什麼,考察面試者是否對新技術足夠敏感。git

  重要程度:3/10程序員

  須要理解的程度:知道這些縮寫(CLR,BCL,FCL,CTS,CLS)各表明什麼便可。github

  1.1 什麼是.NET框架?在各個平臺版本中,有什麼值得強調的更新?面試

  .NET框架是以一種採用系統虛擬機(即CLR)運行的,面向CLR的編程平臺,以CLR爲基礎。數據庫

  .NET的基礎類庫運行於CLR之上(類比Java的虛擬機),做爲其餘各類功能的基石。編程

  .NET框架支持多種語言(C#、F#、、C++、Python等)的開發。json

  它的前身是Windows DNA。如今.NET框架的擴展性甚至超過Java,其的Mono爲Mac OS提供了支持,Xamarin可媲美安卓開發,能夠在任何手機上開發。緩存

  .NET框架是開源的。它的代碼在.NET Foundation · GitHub。若是你的commit有幸被接受,即便改動有多麼微小,也是無上的榮耀,你絕對應該把它寫到你簡歷的第一行,這個成就能夠和「爲Linux內核優化作過貢獻」相比,那可比曾經在BAT作過幾年的經歷牛逼多了。

  全部.NET支持的語言編寫出來的程序,在支持.NET的編譯器編譯以後,會先產出程序集,其主要內容是IL和元數據。以後,JIT再將其翻譯爲機器碼。

  甲骨文公司的Java EE是.NET平臺的競爭對手之一。

  .NET框架如今已經出到了版本4.6.1。在3.0以前,.NET框架的Web解決方案是(Webform & MVC),數據庫鏈接爲(支持過去的ODBC,OLE等,並支持SQL Server和Oracle),Windows Form則做爲Windows下的應用解決方案。

  .NET最重大的一個版本更新是3.0,其中,提出了WCF(統一了過去Web服務混亂的形式,造成了一個統一的格式,並採用SOAP),WPF(做爲Windows form的加強版)以及WF。

  .NET3.5集成了LINQ。另外Entity Framework取代,它對應VS2008。

  .NET4.0提出了任務並行庫和PLINQ。

  .NET 5 (即.NET Core 1.0)在2016年6月27日推出。是次推出伴隨着 Core (即 6)和Entity Framework 7。這些產品將支持Windows,OS X和Linux三種操做系統。

  新版本的.NET項目使用.json文件代替了過去的.xxproj,.sln和.suo文件,這符合目前的主流,即用json代替XML。新版本的.NET框架要傳輸給咱們的理念是:這是一個跨平臺的,開源的框架。

  一切都是依賴注入,一切都是nuget,開發完全組件化,能解耦的全都解耦。

   Core完全擺脫了System.Web這個頑疾,在其中,咱們甚至連MVC都是注入進去的。若是想獲得什麼組件,要麼經過依賴注入,要麼就使用nuget。永遠不要手動add reference,目前我知道的惟一的例外是System.Configuration。

  當你和團隊其餘人並行開發系統的不一樣模塊時,大家能夠用nuget互相獲得對方模塊中的工程。Nuget相比add reference,更不容易出錯,界面更友好,且不會輕易陷入dll陷阱。

  通過.NET牌編譯器編譯以後的程序集有兩種形態:類庫(.dll)形態和可執行文件(.exe)形態。.NET自帶了不少類庫,統稱爲FCL。BCL是FCL的一個子集。

  1.2 基礎類庫(BCL)

  Base Class Library (BCL) 是微軟所提出的一組標準庫,可提供給.NET Framework全部語言使用。隨着 Windows 以及.NET Framework 的成長,BCL 已近乎成爲在.NET上的 Windows API。mscorlib.dll程序集幾乎就是基礎類庫的代名詞。

  當安裝.NET Framework時,全部的基礎類庫被部署到全局程序集緩存(GAC)。它的位置通常在C:\Windows\assembly。因此你不須要在你的工程中手動引用任何的基礎類庫,它們會被自動引用。

  若是你從GAC中刪除了mscorlib.dll,你的IDE將變成一個什麼都不懂的白癡。由於沒有mscorlib.dll,意味着沒有基礎類庫,沒有整型,字符串,控制檯…你什麼都作不了。

  部分mscorlib.dll包括的命名空間:

  System:.NET Framework 類庫中最基底的服務,提供應用程序域 (Application Domain),數據類型,I/O 以及其餘類庫的基礎。

  System.Collections:提供非泛型數據結構以及集合對象的支持,其中 System.Collections.Generic中包括全部的泛型數據結構。

  System.Configuration:提供 .NET 應用程序在配置設置上的支持。

  System.Data: 的組成類庫,爲數據訪問功能的核心功能。

  System.Drawing:提供 .NET 的繪圖能力,包含基本位圖處理以及視頻與色彩處理,打印支持也由本名字空間提供,此名字空間包裝了大多數的 GDI 以及 GDI+ 的 API。

  :提供數據流與文件讀寫的支持

  :.NET 中的網絡功能

  System.Reflection:反射

  System.Diagnostics:.NET 中提供系統診斷,除錯,追蹤與運行外部進程的能力

  System.ServiceModel:WCF 的組成類庫,於 .NET Framework 3.0 時出現。

  System.Text:對文字,編碼以及正規表達式的支持。

  System.Threading:線程控制

  System.Windows.Forms: Windows Forms 的組成類庫,包裝了 Win32 用戶界面,視窗,共用控件,以及 Shell 的基礎 API,以提供設計 Windows 應用程序用戶界面所需的支持。

  System.Windows:WPF 的組成類庫,於 .NET Framework 3.0 時出現。

  System.Web: 的組成類庫,令工程能夠和 IIS 服務器交互,XML Web Service 開發的基本支持也由本類別提供。 Core中消失(若是你不打算用IIS作服務器的容器,則你不須要這個類庫)。

  System.Xml:XML 解析器

  System.Linq,System.Xml.Linq:LINQ 的核心類庫,System.Linq 是 LINQ to Object,而 System.Xml.Linq 則是 LINQ to XML。

  然而在C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\咱們還有一個System.dll,這個參考是每次新建工程時VS自動引用的若干參考之一。這個程序集中也有一個System命名空間,它的內容和mscorlib.dll中的不一樣。

  能夠看到,System這個命名空間存在於不止一個程序集中。這意味着不一樣的程序集能夠共享一個命名空間。

  在System.dll中,System類型擁有Uri這個成員,mscorlib.dll中System類型擁有int這個成員(基元類型)。因此咱們能夠作個試驗,若是咱們將工程中對System的引用去掉,那麼咱們就不能定義一個Uri類型的對象。

  但咱們仍然可使用int類型,由於它雖然也在System這個類型裏面,但位於mscorlib.dll中。當你去掉對System的引用時,你僅僅去掉了System.dll和裏面的功能,但你沒有去掉mscorlib.dll中System類型的功能。

  BCL是屬於整個.NET框架的,並不是某種語言的一個基礎類庫。例如,C#的string類型的全部功能和定義來源於mscrolib.dll中的System.String,而VB的string類型的功能和定義也來源於相同的地方。

  基礎類庫中定義的類型稱爲基元類型,它也是爲.NET框架全部的語言共享。

  1.3 框架類庫(FCL)

  做爲一名.NET程序員,天天都要打交道的就是FCL了(框架類庫)。BCL是FCL的一個子集。簡單來講FCL除了BCL的那部分,就是咱們要引用的外部參考。

  1.4 CTS(公共類型系統)和CLS(公共語言規範)

  簡單的說,CTS就是說話的語法和規範。你能夠理解爲,英語是一種語言,英語的CTS(至少絕大一部分)就是「實用英語語法(張道真)」這本書。若是C#沒了語法,那就沒有class,沒有接口,變成了僞碼。

  參考資料中的第一個連接講的很好,我就在這裏總結一下吧:

  CTS是一套語法。相似「英語語法」。它規定了一套約束,例如英語規定全部的字詞都是由26個字母組成的(以及其餘不少規則)。服從這套語法的語言均可以被當作是英語的某種方言,例如中古英語,現代英語都是英語,而漢語不符合字詞由字母組成,因此它不是英語。同理全部服從CTS的語言,均可以被當作.NET框架的語言。

  CTS中定義了類型,容許它有屬性,字段,方法等。

  .NET框架的衆多語言各自實現了CTS的一部分功能。作一個不太恰當的類比,C#能夠被認爲是「美國英語」,F#是「英國英語」而VB是「印度英語」等。他們是英語的各類方言。他們共享一套相同的詞彙表,但也各有各的特色。例如顏色在英國英語中的拼寫是colour,美國英語則是color。

  因爲.NET框架的衆多語言在編譯時都要轉換爲IL,所以IL實現的CTS功能是它們的並集,也就是CTS所有的功能。你能夠理解爲,雖然.NET框架語言那麼多,但一編譯了以後,就成了一種語言。

  .NET框架的衆多語言分享CTS的一小部分功能,這部分功能稱爲CLS(Common Language Specification,公共語言規範)。這是這些語言(的程序集)能夠相互使用的前提。若是你建立一個新語言,其實現了CTS的一部分功能,但不包括CLS,那你的語言就不能被其餘.NET框架的語言(的程序集)使用。若是你建立的語言甚至不符合CTS,例如你在詞彙表中加入了漢字,那很差意思,你建立的語言不能叫英語。

  很明顯,CLS是CTS的一個子集,並且是最小的子集。(最小功能集)

  1.5 爲何說.NET是平臺無關的?

  .NET程序集能夠在非微軟操做系統如Mac OS,各類版本的Linux,以及iOS和Android移動設備上開發和執行。

  .NET的平臺無關性主要體現爲:.NET程序集能夠在任何的平臺上運行,無論是Windows,仍是Mac,只要這個平臺擁有將IL轉換爲機器碼,以及加載其餘相關程序集的能力(即CLR),而任何機器均可以運行機器碼。

  這相似於Java的虛擬機,只要平臺裝了Java虛擬機,則這個平臺就能夠運行Java程序。

  1.6 CLR(公共語言運行時)

  CLR是讓程序執行所需的外部服務的集合,相似Java須要JVM虛擬機才能夠運行。

  它的核心功能(好比即時編譯,內存管理,程序集加載,安全性,異常處理和線程同步)可由面向CLR的全部語言使用。

  例如,CLR容許建立線程,因此面向CLR的全部語言都能建立線程。

  CLR是.NET的運行基礎,管理.NET程序集的執行。它運行於Windows之上,不少功能僅僅是Windows上的一個wrapper,例如線程,內存管理等,這些其實是Windows在管理。但JIT則是它獨有的,若是沒有它,就不能把IL變成機器碼,計算機也就不認識C#,你也就不能運行C#程序。

  在開始運行.NET程序以前,編譯器將代碼轉換爲IL。

  IL代碼並不能直接運行,CLR將真正須要用到的程序集導入內存,讀取元數據,接着爲類型開闢內存空間,執行全部須要的安全檢查,並最終運行代碼:

  CLR找到代碼中擁有Main方法的類型而且加載這個類型。CLR中一個名爲Class loader(類加載程序)的組件負責這項工做。它會從GAC、配置文件、程序集元數據中尋找這個類型,而後將它的類型信息加載到內存中的數據結構中。在Class loader找到並加載完這個類型以後,它的類型信息會被緩存起來,這樣就無需再次進行相同的過程。固然,若是這個類型引用了其餘的類型,則會致使一連串的程序集加載,這將定義程序代碼執行的環境(相似Java的JVM)。注意即便工程很大,有幾百個程序集,CLR不會所有加載,只會在真正用到該程序集的時候才加載。

  驗證。在CLR中,還存在一個驗證程序(verifier),該驗證程序的工做是在運行時確保代碼是類型安全的。它主要校驗兩個方面,一個是元數據是正確的,一個是IL代碼必須是類型安全的,類型的簽名必須正確。這是早期綁定驗證,驗證在運行時以前發生。對於動態類型,此時不作任何檢查。

  即時編譯。(此時就從編譯時過渡到了運行時)這一步就是將託管的IL代碼編譯爲能夠執行的機器代碼的過程,由CLR的即時編譯器(JIT Complier)完成。即時編譯只有在方法的第一次調用時發生。類型加載程序(Class loader)會爲每一個方法插入一個存根。在調用方法時,CLR會檢查方法的存根,若是存根爲空,則執行JIT編譯過程,並將該方法被編譯後的本地機器代碼地址寫入到方法存根中。當第二次對同一方法進行調用時,會再次檢查這個存根,若是發現其保存了本地機器代碼的地址,則直接跳轉到本地機器代碼進行執行,無需再次進行JIT編譯。JIT編譯還會優化本地的代碼。

  在程序運行時,CLR還負責:

  異常處理

  內存管理與垃圾回收

  線程管理(線程池)

  託管代碼是必須在CLR下執行的代碼,而非託管代碼則不須要CLR的支持就能夠運行。CLR自己用於管理託管代碼,所以它是由非託管代碼編寫的,並非一個包含了託管代碼的程序集,也不能使用IL DASM進行查看。

  它位於C:\%SystemRoot%\\Framework\版本號下,視安裝的機器不一樣有兩個版本,一個是工做站版本的mscorwks.dll,一個是服務器版本的mscorsvr.dll。wks和svr分別表明workstation和server。

  CLR via C#這本書選擇經過C#做爲視角,討論CLR的各類功能。經過對這本書的閱讀,你會對一些實際由CLR進行管理的行爲例如垃圾回收,線程管理有更加深入的認識。

  2. 編譯:IL與JIT

  面試出現頻率:低。不排除部分IL專家會試探性問你一些IL命令,但我相信你答不出來他們也不會在乎。學了IL和沒學,通常人看不出來區別,學了IL,也不意味着你就很厲害。我的認爲,學IL惟一的用處就在於證實你看到的書上寫的各類結論,或者驗證一些性能方面的想法。

  重要程度:3/10,常識性瞭解便可

  須要理解的程度:知道IL是中間代碼,知道JIT的優勢(帶緩存的編譯),以及它可能會對你的代碼進行優化。

  2.1 什麼是IL(CIL)?如何得到IL代碼?

  在.NET的開發過程當中, IL的官方術語是MSIL或CIL(Common Intermediate Language,即公共中間語言)。所以,IL,MSIL和CIL指的是同一種東西。

  當使用支持.NET的編譯器編譯以後,生成.dll或.exe文件。這文件稱做.NET程序集,包含IL和元數據。不一樣語言(例如C#和VB)通過不一樣編譯器(例如C#編譯器和VB編譯器),編譯一段功能類似的代碼(區別僅僅在於語法),其IL也基本類似。雖然IL相對C#較爲底層,但它仍然是一個十分高級的語言。它並非彙編語言。

  能夠經過ildasm(在cmd中運行)工具加載任意的.NET程序集並分析它的內容,包括它所包含的IL代碼和元數據。注意,高級語言只公開了CLR的全部功能的一個子集,而IL容許開發人員訪問CLR全部的功能。

  2.2 什麼是JIT?還有什麼其餘編譯方式?什麼時候使用到JIT?

  即時編譯(英語:Just-in-time compilation)是動態編譯的一種形式,是一種提升程序運行效率的方法。一般,程序有兩種運行方式:靜態編譯與動態編譯。靜態編譯的程序在執行前所有被翻譯爲機器碼,而動態編譯執行的則是一句句,邊運行邊翻譯。

  即時編譯則混合了這兩者,一句句編譯源代碼,可是會將翻譯過的代碼緩存起來以下降性能損耗。相對於靜態編譯代碼,即時編譯的代碼能夠處理延遲綁定並加強安全性。

  CLR的JIT負責將IL編譯成機器碼。 當程序編譯成程序集以後,CLR加載任何須要用到的其餘程序集,並開始使用JIT將CIL編譯爲機器碼。

  JIT編譯器會在方法的首次調用時,從類型的元數據中查找方法,並進行檢查,例如檢查類型是否安全。若是出現了問題,則觸發運行時錯誤。之後對方法的全部調用都以本地代碼的形式全速運行,無須從新檢查。

  2.3 本地代碼的優化

  CLR的JIT編譯器會對本地代碼進行優化。例如字符串駐留中對常量字符串相加的優化。和沒有優化相比,優化以後的代碼將得到更出色的性能。但過分的優化可能會出現問題,在CLR via C#的易失構造中,做者舉了一個例子。

  class Program

  {

  private static bool s_stopWorker = false;

  static void Main()

  {

  Console.WriteLine("Main: letting worker run for 2 seconds");

  Thread t = new Thread(Worker);

  t.Start();

  Thread.Sleep(2000);

  s_stopWorker = true;

  Console.WriteLine("Main: waiting for worker to stop");

  t.Join();

  }

  private static void Worker(object o)

  {

  int x = 0;

  while (!s_stopWorker)

  {

  x++;

  }

  Console.WriteLine("Worker: stopped when x = {0}", x);

  }

  }

  若是使用f5呼叫出Visual Studio的調試模式,則程序會像預期的那樣正常運行直到結束。使用調試器會形成JIT編譯器在Debug模式進行編譯,它生成未優化的代碼,目的是方便你進行單步調試。若是是選擇了x86的Release模式進行編譯:

  它將會生成被CLR優化的代碼。值得一提的是,x86編譯器是一個更成熟的編譯器,執行優化比x64更大膽。x64不會執行上面所說的特定的優化。在再次用f6進行編譯以後,用ctrl+f5運行程序,程序將會陷入無限循環。

  注意:必須用x86+Release編譯,而後以非調試模式運行(即Ctrl+F5),才能看到這個效果。問題發生的緣由是,x86的編譯優化過分。它發現變量s_stopWorker要麼爲true要麼爲false。

  它還發現這個值在worker方法自己中歷來沒有變化。所以,編譯器會生成代碼檢查s_stopWorker,若是s_stopWorker爲true,就顯示「Worker: stopped when x = 0」。若是s_stopWorker爲false編譯器就生成代碼進入一個無限循環,並一直遞增x。解決的辦法是爲s_stopWorker加入修飾詞volatile。

  PDB文件包含了能夠令調試器在本地工做的信息。能夠這麼說:有了PDB文件,本地的debug才成爲可能。若是你打算髮布Release版本,則不須要該文件。使用Release模式編譯的結果中也不包含PDB文件。

  例如,你寫了一個小的控制檯程序給別人用,那麼你不須要把\bin\debug裏面全部的文件都拷貝給別人,你只須要程序自己,必要的dll和config文件便可。

本文摘自:

相關文章
相關標籤/搜索