.NET基礎面試題整理

來源:互聯網
上載者:User

標籤:blog   http   io   os   使用   ar   java   for   strong   

今年畢業,本學期找工作期間在面試前做的一些臨時的準備

以下的關於老趙分享的面試題解答參考了手頭的書籍和視頻教程,以及網上的資料,現整理出來希望對大家有所協助,不對或欠佳的地方望大家指出來我好改正。

1.什麼是.NET?什麼是CLI?什麼是CLR?IL是什嗎?

 

(1).net用於代碼編譯和執行的整合託管環境,換句話,它管理應用程式啟動並執行方方面面,包括首次啟動並執行編譯,為程式分配記憶體
儲存資料和指令,對於應用程式授予或拒絕相應的許可權,並啟動管理應用程式的執行,剩餘記憶體的在分配。由於所有.net應用程式
都是在.net framework上面執行,所以開發人員只需考慮與.net framework打交道,而不必關係和底層作業系統上面的實現
包括CLR和BCL


(2).CLI(common language infrastructure)通用語言基礎結構,一項國際性的標準,沒有規定標準具體如何?。相反,它描述了一個
CLI平台在符合標準的前提下應該具有什麼行為。包含了:運行時(CLR),通用中間語言(CIL),公用類型系統(CTS),
Common Language Specification(CLS),中繼資料(Metadata),架構(framework)


(3)CLR:通用語言執行平台,負責載入和運行程式  IL:中繼語言,C#編譯器將C#代碼轉換成IL,運行時能夠理解IL,並編譯成機器碼 

2.JIT是什麼,它是如何工作的?GC是什麼,簡述一下GC的工作方式?

 

JIT:Just in time,C#或者是VB.NET的代碼首先被編譯為IL儲存在本地,當要運行這些代碼的時候,CLR對IL進行第二次編譯轉換成機器碼運行。好處:可移植性,而且IL在載入到記憶體中時將受到型別安全方面檢查,這實現了更好的安全性和可靠性。

 GC:記憶體回收(garbage collection),是根據程式的需要自動分配和回收記憶體的過程。記憶體回收行程處理的是引用對象,而且只回收堆上的記憶體。這意味著假如維持對一個對象的引用,就會阻止GC重用對象使用的記憶體。在.NET中,記憶體回收行程採用的是mark-and-compact演算法。在一次記憶體回收周期開始的時候,它要識別對象的所有跟引用,根據這個引用可以遍曆每個根引用所標識的一個樹形結構,並遞迴確定所有引用指向的對象。這樣一來,記憶體回收行程就可以識別所有可達的對象,在執行回收的時候,GC不是枚舉所有訪問不到的對象,相反,通過壓縮所有相鄰的可達的對象來執行記憶體回收。不可訪問的對象就會被覆蓋。記憶體回收的宗旨是提高記憶體的利用率,它並不是用來清理檔案控制代碼,和資料庫連接字串,連接埠或者其他有限的資源(終接器finalizer,不能被顯示調用,不能傳遞任何參數,即不能被重載,只有記憶體回收行程才能調用終接器,使用Using語句進行確定性終結 

 3.類(class)和結構(struct)的區別是什嗎?它們對效能有影響嗎?

1. 實值型別與參考型別 

結構是實值型別:實值型別在棧上分配地址,所有的基底類型都是結構類型,例如:int 對應System.int32 結構,通過使用結構可以建立更多的實值型別 
類是參考型別:參考型別在堆上分配地址堆棧的執行效率要比堆的執行效率高,可是堆棧的資源有限,不適合處理大的邏輯複雜的對象。所以結構處理作為基底類型對待的小對象,而類處理某個商業邏輯因為結構是實值型別所以結構之間的賦值可以建立新的結構,而類是參考型別,類之間的賦值只是複製引用 
註:1.雖然結構與類的類型不一樣,可是他們的基底類型都是對象(object),c#中所有類型的基底類型都是object
2.雖然結構的初始化也使用了New 操作符可是結構對象依然分配在堆棧上而不是堆上,如果不使用“建立”(new),那麼在初始化所有欄位之前,欄位將保持未賦值狀態,且對象不可用

 2.繼承性

結構:不能從另外一個結構或者類繼承,本身也不能被繼承,雖然結構沒有明確的用sealed聲明,可是結構是隱式的sealed . 
類:完全可擴充的,除非顯示的聲明sealed 否則類可以繼承其他類和介面,自身也能被繼承註:雖然結構不能被繼承 可是結構能夠繼承介面,方法和類繼承介面一樣

3.內部結構: 
結構: 沒有預設的建構函式,但是可以添加建構函式沒有解構函式沒有 abstract 和 sealed(因為不能繼承)不能有protected 修飾符可以不使用new 初始化在結構中初始化執行個體欄位是錯誤的 
類: 有預設的建構函式 有解構函式 可以使用 abstract 和 sealed 有protected 修飾符 
必須使用new 初始化

4..NET BCL裡有哪些是類(結構),為什麼它們不是結構(類)?

結構:System.Boolean  Byte   Char  Decimal Double  Int32 
堆棧的空間有限,對於大量的邏輯的對象,建立類要比建立結構好一些 大多數情況下該類型只是一些資料時,結構時最佳的選擇
類:String Object Delegate 介面 等等 包含了大量的邏輯對象,表現抽象 

 5.在自訂類型時,您如何選擇是類還是結構?

1). 堆棧的空間有限,對於大量的邏輯的對象,建立類要比建立結構好一些 
2). 結構表示如點、矩形和顏色這樣的輕量對象,例如,如果聲明一個含有 1000 個點對象的數組,則將為引用每個對象分配附加的記憶體。在此情況下,結構的成本較低。 
3). 在表現抽象和多層級的對象層次時,類是最好的選擇
4). 大多數情況下該類型只是一些資料時,結構時最佳的選擇 

6.在.NET程式運行過程中,什麼是堆,什麼是棧? 

棧通常儲存著我們代碼執行的步驟,而堆上存放的則多是對象,資料等。我們可以把棧想象成一個接著一個疊放在一起的盒子。當我們使用的時候,每次從最頂部取走一個盒子。棧也是如此,當一個方法(或類型)被調用完成的時候,就從棧頂取走(called a Frame,譯註:調用幀),接著下一個。堆則不然,像是一個倉庫,儲存著我們使用的各種對象等資訊,跟棧不同的是他們被調用完畢不會立即被清理掉。
棧記憶體無需我們管理,也不受GC管理。當棧頂元素使用完畢,立馬釋放。而堆則需要GC(Garbage collection:垃圾收集器)清理 

7.什麼情況下會在堆(棧)上分配資料?它們有效能上的區別嗎?“結構”對象可能分配在堆上嗎?什麼情況下會發生,有什麼需要注意的嗎?

1)實值型別一般分配在對上面,參考型別分配在堆上面。棧的效率要高於堆。
2)可能,當在類中定義一個結構類型時,該結構就分配在堆上 

8.泛型的作用是什嗎?它有什麼優勢?它對效能有影響嗎?它在執行時的行為是什嗎?

作用:為了促進代碼的重用,尤其是演算法的重用
優勢:(1)可重用性(2)型別安全,在參數化類別中只有成員明確希望的資料類型才可以使用(3)效能:避免了從Object的強制轉換和實值型別的裝箱(4)減小了記憶體消耗:避免裝箱也就不在需要消耗堆上的記憶體。
執行時的行為:泛型也是對象,泛型類的“型別參數”變成了中繼資料;CLR會在需要的時候構造利用它們的類。一個泛型類經過編譯好之後和普通的類並沒有什麼區別。編譯的結果只有中繼資料和CIL。基於實值型別的泛型執行個體化:CLR會講指定的型別參數放到CIL中合適的位置,從而建立一個具體化的泛型型別。所以CLR會為沒個新的參數值建立具體的泛型型別
基於參考型別的執行個體化:CLR會建立一個具體化的泛型型別。以後,每次用一個參考型別參數來說執行個體化一個構造好的類型時,並在CIL中用Object引用替換型別參數,CLR都會重用以前產生好的泛型版本

 9..NET BCL中有哪些泛型型別?舉例說明平時編程中您定義的泛型型別。

List<T>:通過索引訪問強型別的列表
Dictionary<T>:表示索引值對的集合
Queue<T>:隊列  Stack<T>: 棧
購物車用Dictionary類比,OA中擷取員工列表等資料的時候,傳回值是泛型的

 10.異常的作用是什嗎?.NET BCL中有哪些常見的異常?在代碼中您是如何捕獲/處理異常的?在“catch (ex)”中,“throw”和“throw ex”有什麼區別?您會如何設計異常的結構,什麼情況下您會拋出異常?

(1)C# 語言的異常處理功能可協助您處理常式運行時出現的任何意外或異常情況
(2)throw會保留堆棧資訊。throw ex 不會。當然,如果你拋出新的異常之前設定innerException的話,可以通過innerException的堆棧訪問原有的堆棧。
(3)靠異常才能發現錯誤的,通過try catch finally來捕獲異常。如果是未預料到的則不處理(記憶體不足,刪除檔案)直接報錯更容易發現錯誤catch塊從最具體到常規排列

11.List<T>和T[]的區別是什麼,平時你如何進行選擇?Dictionary<TKey, TValue>是做什麼的?.NET BCL中還有哪些常用的容器?它們分別是如何?的(哪種資料結構)?分別是適用於哪些情境?


1.List<T>arrylist的泛型版本,大小是可變的,T[]繼承自Array,大小是固定的。如果大小沒有怎麼變化,選擇T[],一般情況下選擇List<T>
2.Dictionary是hashtable的泛型版本,用來儲存索引值對的.例如:sortlist,stack等

12抽象類別和介面有什麼區別?使用時有什麼需要注意的嗎?


如何選擇是定義一個“完全抽象”的抽象類別,還是介面?什麼是介面的“顯式實現”?為什麼說它很重要?
相同點:都不能被直接執行個體化,都通過繼承實現其抽象方法
不同點: 
(1) 介面支援多繼承;抽象類別不能實現多繼承。 
(2) 介面只能定義行為;抽象類別既可以定義行為,還可能提供實現。
(3) 抽象類別允許包含實現的virtual成員,所以能為衍生類別成員提供一個預設的實現,而介面所有的成員自動成為virtual成員,而且不能包含任何實現

13.字串是參考型別類型還是結構類型? 參考型別


它和普通的參考型別相比有什麼特別的地方嗎?不可變的
使用字串時有什麼需要注意的地方?為什麼說StringBuilder比較高效?
當拼接兩個字串時,系統先是把兩個字串寫入記憶體,接著刪除原來的String對象,然後建立一個String對象,並讀取記憶體中的資料賦給該對象。這一來二去的,耗了不少時間。而使用System.Text命名空間下面的StringBuilder類就不是這樣了,它提供的Append方法,能夠在已有對象的原地進行字串的修改,簡單而且直接。
在串連多個字串時,它無論何時都比直接相加更高效嗎?
不一定,在1000個字元以內效果一樣,達到10000時StringBuilder類的效率會顯著提升
如何高效地進行數組複製?“二維數組”和“數組的數組”有什麼區別?
數組複製的方法:for  CopyTo()  靜態CopyTo()  Clone

14.什麼是元編程,.NET有哪些元編程的手段和情境?什麼是反射?能否舉一些反射的常用情境?有人說反射效能較差,您怎麼看待這個問題?有什麼辦法可以提高反射的效能嗎?


學著做OA的時候,動態載入不同的DataProvider(Oracle和Sqlserver),方便,可以隨時替換不用重新編譯器

15.委託是什嗎?匿名方法是什嗎?在C# 3.0中,Lambda運算式是什嗎?擴充方法是什嗎?LINQ是什嗎?您覺得C# 3.0中還有哪些重要的特性,它們帶來了什麼優勢?BCL中哪些類庫和這些特性有關?您平時最常用哪些?


委託可以把一個方法作為參數代入另一個方法。
委託可以理解為指向一個函數的指標。
匿名方法:就是沒有實際方法聲明的委託執行個體。或者說,它們的定義是直接內嵌在代碼中的。
Lambda運算式:是比匿名方法更加簡潔的一種匿名函數文法
委託和事件沒有可比性,因為委託是類型,事件是對象,下面說的是委託的對象(用委託方式實現的事件)和(標準的event方式實現)事件的區別。事件的內部是用委託實現的。因為對於事件來講,外部只能“註冊自己+=、登出自己-=”,外界不可以登出其他的註冊者,外界不可以主動觸發事件,因此如果用Delegate就沒法進行上面的控制,因此誕生了事件這種文法。事件是用來閹割委託執行個體的,類比用一個自訂類閹割List。事件只能add、remove自己,不能賦值。事件只能+=、-=,不能= 。事件內部就是一個private的委託和add、remove兩個方法。

16.工作之外您看哪些技術相關的書、網站、社區、項目等等?


您還接觸哪些.NET以外的技術,能和.NET或.NET中有針對性的部分做個對比嗎?
C#本質論,SQL Server2008實戰,資料結構,ASP.NET揭秘,Javascript深入淺出

17.website和webapplication的區別


1)website修改後不需要重啟即可看到效果,webapplication需要
2)website不分namespace,webapplication有namespace
3)website為了相容asp轉過來的開發人員習慣
4)沒有技術上的區別,調試習慣不同
5)website為每個編譯為一個dll,webapplication產生一個dll
6)不利於工程開發,比如代碼出錯不容易發現

18.提交到伺服器的表單要設定name,id可以不設定,伺服器只用name,Dom用id

19.為了區分是第一次進入頁面還是點擊提交以後重新進入,form有一個隱藏欄位:


<input type=“hidden” name=“ispostback” value=“true”/>,如果從Request中讀取到ispostback=true,說明點擊提交按鈕提交進入ashx,否則是第一次進入ashx

20.Http是要求-回應模型,伺服器不會讀取瀏覽器的網頁,能夠得到的就是網頁提交過來的資料。

21.get與post提交的比較


Get:通過URL傳遞表單的值(預設),?...&,安全性低,傳遞比較小的資料。
Post:傳遞的值隱藏在http報文中,URL中看不到,重新整理頁面會彈出提示對話方塊如果

22. 實現p內文本自增,因為伺服器不記得上次給瀏覽器的值是多少,而且不像input那樣會將上次的值重新提交回來,因此瀏覽器需要用一個隱藏的欄位將上次的值儲存下來

23.ViewState實現原理


非表單元素無法將用戶端的元素值傳遞給服務端,即使是表單元素也只能傳遞value值,對於其他屬性值,比如背景顏色,大小等也是無法傳遞的,因此對於這些值都要存在隱藏欄位中。Viewstate是跟頁面相關的,不用的頁面viewstate也會不同,不會相互影響。ViewState對需要PostBack處理的頁面才可能有用,對於新聞展示這類頁面不需要互動,完全可以禁用ViewState來提升效能。如果完全沒有ViewState,則頁面中不能有runat=server的form

 
24.Cookie


表單是和頁面相關的,只有瀏覽器提交了這些資料服務器才能得到,Cookie是和網站相關的,每次向伺服器請求的時候除了發送表單資料外,還會將和網站相關的所有Cookie都提交給伺服器,這是強制性的
缺點:不能儲存過多的資訊,安全性差
針對互連網的最佳化:圖片伺服器和主站網域名稱不一樣

25.http請求,css,js,圖片,單獨請求,200表示處理成功,301重新導向,400錯誤請求

 307臨時重新導向,404頁面未找到,403禁止,401未認證,500server內部錯誤,503訪問人數過多。

26./:網站根目錄,../上一級目錄,./目前的目錄,~/應用程式根目錄

27.資料庫查詢效能最佳化

 

1)select中只返回需要的列
2)在減少使用列的同時,考慮減少行,使用where子句
3)只在需要的時候用order by
4)避免在from,where和having子句中隱式資料類型的轉換

常見的排序演算法:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Sort{   public class Sort   {      ///<summary>      /// 插入排序--穩定排序      ///</summary>      ///<param name="list"></param>      public static void InsertSort(List<int> list)      {         int j, tmp;         for (int i =1; i < list.Count; i++)         {            j = i;            tmp = list[i];            while (j >0&& tmp <= list[j -1])            {               list[j] = list[j -1];               j--;            }            list[j] = tmp;         }      }      ///<summary>      /// 希爾排序      ///</summary>      ///<param name="list"></param>      public static void ShellSort(List<int> list)      {         int j, tmp;         int h =3;         while (h>0)         {            for (int i = h; i < list.Count; i++)            {               tmp = list[i];               j = i;               while ((j > h -1) && tmp < list[j - h])               {                  list[j] = list[j - h];                  j -= h;               }               list[j] = tmp;            }            h = (h -1) %3;         }      }      ///<summary>      /// 冒泡排序--穩定排序      ///</summary>      ///<param name="list"></param>      public static void BubbleSort(List<int> list)      {         if (list ==null|| list.Count <1)         {            return;         }         int tmp;         for (int i =0; i < list.Count -1; ++i)         {            bool flag=false;            for (int j = list.Count -1; j >i+1; j--)            {               if (list[j] > list[j +1])               {                  tmp = list[j];                  list[j] = list[j +1];                  list[j +1] = tmp;                  flag=true;               }               if(flag==false)               {                  return;               }            }         }      }      ///<summary>      /// 選擇排序--直接選擇排序      ///</summary>      ///<param name="list"></param>      public static void SelectSort(List<int> list)      {         int min, tmp;         for (int i =0; i < list.Count; i++)         {            min = i;            for (int j = i +1; j < list.Count; j++)            {               if (list[j] < list[min])               {                  min = j;               }            }            if (i != min)            {               tmp = list[i];               list[i] = list[min];               list[min] = tmp;            }         }      }      ///<summary>      /// 堆排序      ///</summary>      ///<param name="list"></param>      public static void HeapSort(List<int> list)      {         int n = list.Count;         for (int i = n/2-1; i >=0; i--)         {            Sift(list, i, n -1);         }         for (int i = n -1; i >=1; i--)         {            int tmp = list[0];//取堆頂元素            list[0] = list[i];//讓堆中最後一個元素上移到堆頂位置            list[i] = tmp;//此時list[i]已不在堆中,用於存放排好序的元素            Sift(list, 0, i -1);//重新調整堆         }      }      private static void Sift(List<int> list, int low, int high)//建堆過程      {         //i為欲調整子樹的根結點的索引號,j為這個結點的左孩子         int i = low, j =2* i +1;         int tmp = list[i];//記錄雙親結點的值         while (j<=high)         {//如果左孩子小於右孩子,則將欲交換的孩子結點指向右孩子            if (j < high && list[j] < list[j +1])            {               j++;//j指向右孩子            }            if (tmp < list[j])//如果雙親結點小於它的孩子結點            {               list[i] = list[j];//交換雙親結點和它的孩子結點               i = j;//以交換後的孩子結點為根,繼續調整它的子樹               j =2* i +1;//j此時代表交換後的孩子結點的左孩子            }            else//調整完畢            {               break;            }         }         list[i] = tmp;//使最初被調整的結點放入正確的位置      }      ///<summary>      /// 歸併排序--穩定排序      ///</summary>      ///<param name="list"></param>      ///<param name="low"></param>      ///<param name="high"></param>      public static void MergeSort(List<int> list, int low, int high)      {         if (low < high)         {            int mid = (low + high) /2;            MergeSort(list, low, mid);            MergeSort(list, mid +1, high);            Merge(list, low, mid, high);         }      }      private static void Merge(List<int> list, int low, int mid, int high)      {//listTmp為臨時存放空間,存放合并後的資料         List<int> listTmp =new List<int>(high - low +1);         int i = low, j = mid +1, k =0;//k為listTmp的下標         while (i <= mid && j <= high)         {            listTmp[k++] = (list[i] < list[j]) ? list[i++] : list[j++];         }         while (i <= mid)         {            listTmp[k++] = list[i++];         }         while (j <= high)         {            listTmp[k++] = list[j++];         }         for (i = low, k=0; i <= high;i++,k++ )         {            list[i] = listTmp[k];         }      }      ///<summary>      /// 快速排序      ///</summary>      ///<param name="list"></param>      public static void QuickSort(List<int> list)      {         QuickSort(list, 0, list.Count -1);      }      public static void QuickSort(List<int> list, int low, int high)      {         if (low < high)         {            int i = low, j = high, tmp = list[i];            while (i < j)            {               while (i < j && list[j] >= tmp)               {                  j--;               }               list[i] = list[j];               while (i < j && list[i] <= tmp)               {                  i++;               }               list[j] = list[i];            }            list[i] = tmp;            QuickSort(list, low, i -1);            QuickSort(list, i +1, high);         }      }   }}

收集自:Gabriel Zhang

.NET基礎面試題整理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.