C#&.NET高級面試題


轉自http://chaoyouzhuo.blog.163.com/blog/static/1263760012011109114131316/

1. DateTime.Parse(myString); 這段代碼有什么問題?

A:區域信息即CultureInfo沒有指定。如果不指定的話,它將采用默認的機器級的設置(見:控制面板->區域和語言選項)並使用這個設置來決定這個字符串即myString怎樣被解釋。所以如果你傳入“5/2/2005”且你的區域設置為En-US,則它會被解釋為May 2nd 2005,但是如果你的區域設置為Hindi-India,則它會被解釋為5th Feb 2005!

參考下面的代碼示例:

string sDate = "5/2/2005"; //本意是2005年5月2號

DateTime[] dt = new DateTime[3];

CultureInfo[] cf = new CultureInfo[3];

cf[0] = new CultureInfo("en-US", true); //指定為en-US,字符串將被解釋為“MM/DD/YYYY”

dt[0] = DateTime.Parse(sDate, cf[0], DateTimeStyles.AllowWhiteSpaces);

dt[0] = dt[0].AddMonths(1); //另日期變為2005年6月2日

Console.WriteLine(dt[0].ToString(cf[0]));

cf[1] = new CultureInfo("hi-IN", true); //這是印度格式,字符串被解釋為“DD/MM/YYYY”

dt[1] = DateTime.Parse(sDate, cf[1], DateTimeStyles.AllowWhiteSpaces);

dt[1] = dt[1].AddMonths(1); //讓它變成2005年3月5日

Console.WriteLine(dt[1].ToString(cf[1]));

好了,這解決所有問題了嗎?沒有!

如果時間放在一個文本框中 – 有些人輸入了“2005/02/05” – 我不知道我應該怎樣解釋這個輸入呢! “DateTime.ParseExact” 要求你必須告訴計算機怎樣處理輸入的日期字符串它才可以處理。

//拋出FormatException

cf[2] = new CultureInfo("hi-IN", true);

dt[2] = DateTime.ParseExact(sDate, new string[] { "d" }, cf[2], DateTimeStyles.AllowWhiteSpaces); //拋出Format Exception

dt[2] = dt[2].AddMonths(1);

Console.WriteLine(dt[2].ToString(cf[2]));

第二個參數指定了輸入字符串的格式 – “d”意思是短日期 – MM/dd/yyyy – 查看.net文檔中的DateTimeFormatInfo類中全部的格式。

上面的代碼會拋出一個FormatException,因為你沒有遵守規則。

好了,現在我們幾乎完成了,如果想讓一個字符串表達式被接受怎么辦呢?

使用一個自定義表達式。如下:

sDate = "2005/05/02";

dt[2] = DateTime.ParseExact(sDate, new string[] { "%yyyy/MM/dd" }, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces);

dt[2] = dt[2].AddMonths(1);

Console.WriteLine(dt[2].ToString(cf[2]));

這樣就可以接受了

2. PDB是什么東西?在調試時它應該放在哪里?

A:以下是摘自MSDN一段說明A program database file (extension .pdb) is a binary file that contains type and symbolic debugging information gathered over the course of compiling and linking the project. A PDB file is created when you compile a C/C++ program with /ZI or /Zi or a Visual Basic, Visual C#, or JScript program with the /debug option. Object files contain references into the .pdb file for debugging information. For more information on pdb files, see PDB Files (C++). A DIA application can use the following general steps to obtain details about the various symbols, objects, and data elements within an executable image.

翻譯后(部分):程序數據庫文件(擴展名:pdb)是一個二進制文件包含了在編譯和鏈接項目過程中收集的類型與符號調試信息。PDB文件在你使用/ZI或/Zi參數編譯一個C/C++程序或使用/debug參數編譯一個Visual Basic, Visual C#或Jscript程序時生成。目標文件含有到.pdb文件的引用以查找調試信息。

下面是查詢此文件內容的方法:

u Acquire a data source by creating an IDiaDataSource interface.

u Call IDiaDataSource::loadDataFromPdb or IDiaDataSource::loadDataForExe to load the debugging information.

u Call IDiaDataSource::openSession to open an IDiaSession to gain access to the debugging information.

u Use the methods in IDiaSession to query for the symbols in the data source.

u Use the IDiaEnum* interfaces to enumerate and scan through the symbols or other elements of debug information.

調試時,PDB文件應該與待調試文件放在同一目錄下。

3. 什么是圈復雜度(Cyclomatic Complexity)?為什么它很重要?

A:圈復雜度一種代碼復雜度的衡量標准,中文名稱叫做圈復雜度。在軟件測試的概念里,圈復雜度“用來衡量一個模塊判定結構的復雜程度,數量上表現為獨立現行路徑條數,即合理的預防錯誤所需測試的最少路徑條數,圈復雜度大說明程序代碼可能質量低且難於測試和維護,根據經驗,程序的可能錯誤和高的圈復雜度有着很大關系”。

4. 寫一個標准的lock(),在訪問變量的前后創建臨界區,要有“雙重檢查”。

A: 這即是Jeffrey Richter在其經典著作CLR Via C#中提到的雙檢鎖(double-check locking)技巧。如下是原書代碼:

public sealed class Singleton

{

private static Object s_lock = new Object();

private static Singleton s_value;

//私有構造器組織這個類之外的任何代碼創建實例

private Singleton() { }

// 下述共有,靜態屬性返回單實例對象

public static Singleton Value

{

get

{

// 檢查是否已被創建

if (s_value == null)

{

// 如果沒有,則創建

lock (s_lock)

{

// 檢查有沒有另一個進程創建了它

if (s_value == null)

{

// 現在可以創建對象了

s_value = new Singleton();

}

}

}

return s_value;

}

}

}

5. 什么叫FullTrust?放入CAC的assembly是否是FullTrust的?

FullTrust權限基本上允許跳過所有的CAS驗證,持有該權限的程序集能夠訪問所有的標准權限。GAC中的程序集是具有FullTrust權限的。詳細信息參見此文章

6. 代碼加上需要安全權限的特性有什么好處?

A: 有可能會通過具有元權限程序集或permview.exe工具訪問這些attribute及其參數。有可能在程序集級別使用其中的一些attribute。可以通過反射訪問設置信息。最關鍵一點使程序集開始執行時而不是在執行期間聲明需要權限,這樣可以確保用戶不會在程序開始工作后遇到障礙。

7. gacutil /l | find /i “Corillian”這句命令的作用是什么?

A: gacutil全稱.NET Global Assembly Cache Utility。參數/l [ <assembly_name> ]的作用:列出通過 <assembly_name> 篩選出的全局程序集緩存。find命令作用:在文件中搜索字符串,其參數/i作用是搜索字符串時忽略大小寫。所以這條命令的意思就是在所有的全局程序緩存中搜索名稱包含字符串”Corillian”的程序集。

8. sn -t foo.dll這句命令的作用?

A: sn是.NET Framework 強名稱實用工具,其中參數-T[p] <assembly>作用是顯示 <assembly> 的公鑰的標記(如果使用了-Tp,則還同時顯示公鑰本身)。此命令顯示了foo.dll的公鑰。如果foo.dll非強名程序集產生如下提示:未能將密鑰轉換為標記 -- 程序集“(null)”的公鑰無效。

9. DCOM需要防火牆打開哪些端口?端口135是干嘛用的?

A: DCOM動態的選擇1024~65535之間的網絡端口。此外,DCOM要用135端口實現一些重要的功能。DCOM是使用RPC進行通訊的。利用RPC功能進行通信時,就會向對方電腦的135端口詢問可以使用那個端口進行通訊。這樣,對方的電腦就會告知可以使用的端口號,實際的通訊將使用這個端口來進行。

135端口起的是動態的決定實際的RPC通訊使用的端口映射功能,主要用於使用RPC(Remote Procedure Call,遠程過程調用)協議並提供DCOM(分布式組件對象模型)服務。

10. 對比OOP和SOA,它們的目的分別是什么?

面向對象主要用於對具體的事物進行抽象建模,而SOA的主要目的是定義部署和管理服務的方式,采用SOA的架構可以提高可重用性,降低總成本,提高快速修改與演化IT系統的能力。

11. XmlSerializer是如何工作的?使用這個類的進程需要什么ACL權限?

XmlSerializer提供了方法,使你能夠將自己的對象序列化和反序列化為XML,同時在這個過程中提供一定的控制。這個過程由一些attribute來控制。以下是代碼示例:

序列化:

Theater theater = … ;

XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );

FileStream fs = new FileStream( args[0], FileMode.Create );

xs.Serialize( fs, theater );

反序列化:

XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );

FileStream fs = new FileStream( args[0], FileMode.Open );

Theater theater = (Theater)xs.Deserialize( fs );

控制這個過程:

[XmlRoot( "theater" )] -- 序列化xml的根節點

[XmlElement( "name" )] -- 序列化為xml的元素及元素名稱

[XmlAttribute( "minutes" )] -- 序列化為xml中的特性及其名稱

[XmlElement( "showing", DataType="time" )] -- 序列化為xml的元素及其類型

ACL權限上需要執行程序集的用戶擁有對C:\WINDOWS\Temp\的訪問權限

12. 為什么不提倡catch(Exception)?

Exception類包含許多子類,程序執行的時候要將每一個類都搜索一遍以找到符合的異常類,這樣是蠻消耗資源的,影響程序運行效率。另外,只捕捉特定環境,特定條件下的異常,並進行處理。不應該捕捉所有異常,因為有些異常是我們所無法預料到的,比如,內存溢出或其他錯誤,這種情況下,不應該讓系統以一種未知狀態繼續運行。

13. Debug.Write和Trace.Write有什么不同?何時應該使用哪一個?

Debug類提供一組幫助調試代碼的方法和屬性。Trace類提供一組幫助跟蹤代碼執行的方法和屬性,通俗的說就是為在不打斷程序的調試或跟蹤下,用來記錄程序執行的過程。

Debug只在debug狀態下會輸出,Trace在Release下也會輸出,在Release下Debug的內容會消失。

14. Debug Build和Release Build的區別,是否會有明顯的速度變化?請說明理由。

首先以一個表格說明問題:

項目

Debug

Release

條件編譯常數

Debug;Trace

Trace

優化代碼

False

True

輸出路徑

bin\Debug

bin\Release

生成調試信息

True

False

Debug模式下生成的程序集為調試版本,未經優化;在bin\debug\目錄中有兩個文件,除了要生成的.exe或.dll文件外,還有個.pdb文件,這個.pdb文件中就記錄了代碼中的斷點等調試信息;Release模式下不包含調試信息,並對代碼進行了優化,\bin\release\目錄下只有一個.exe或.dll文件。在項目文件夾下除了bin外,還有個obj目錄。編譯是分模塊編譯的,每個模塊的編譯結果就保存在了obj目錄下。最后會合並為一個exe或者dll文件保存到bin之中。因為每次編譯都是增量編譯,也就是只重新編譯改變了的模塊,所以這個obj的目錄的作用就是保存這些小塊的編譯結果,加快編譯速度。

15. JIT是以assembly為單位發生還是以方法為單位發生?這對於工作區有何影響?

JIT編譯是以方法為單位完成的,當用到相應的方法才把其編譯執行,並將編譯結果暫存當下一次用到時就不用再編譯。可以一定程度上提高效率。

16. 對比抽象基類和接口的使用

如果要讓自定義類包含基類的實現,應該選用抽象基類,接口多做契約使用。.NET中類只允許單繼承,但接口允許多繼承。

17. a.Equals(b)和a==b相同嗎?

對於值類型的比較兩者效果相同(值類型ValueType重寫了Equals方法)。對於除string以外的引用類型==比較對象是否為同一引用,對於string,==比較字符串的內容。而Equals方法對所有引用對象都是比較其是否為同一對象的引用。

很多自定義類都會重寫Equals所以不要只注意默認實現。

18. 在對象比較中,對象一致和對象相等分別是指什么?

對象一致指的是兩個對象是否指向托管堆中同一個目標,其比較對象的類型與值兩個方面。對象相等指的是兩個對象中的數據成員是否相等。前者是一種淺比較,后者是一種深比較。

19. 在.NET中如何實現深拷貝(deep copy)?

實現深拷貝的程序結構基本如下:

示例代碼:

//實現ICloneable接口

public class Copy:ICloneable  
{

//實現ICloneable接口的Clone()方法 
public override object Clone()

{

//在此實現深拷貝

      } 
}

實現深拷貝的代碼中,新建一個對象,然后將對象的成員逐個賦值給新對象的成員。最后將新對象返回。

20. 請解釋一下ICloneable

當用戶需要實現除MemberwiseClone之外的拷貝方法時(如深拷貝),用戶可以實現ICloneable接口,並重寫Clone()方法。在Clone()方法中編寫自己的實現。

21. 什么叫裝箱。

將值類型對象放到托管堆中需要一個裝箱操作。需要裝箱的情況有很多,比如將值類型數據存入一個數組(Array類)時,值類型會被裝箱然后存入托管堆。

22. string是值類型還是引用類型?

string這個引用類型是非常特殊一個引用類型。

它有兩點特殊的地方。第一點對象分配的特殊。例如,有如下語句:

string str1 = "abcd";

string str2 = "abcd";

那么.net在分配string類型的時候,先查看當前string類型列表是否有相同的,如果有的話,直接返回其的引用,否則重新分配。

第二點對象引用操作的特殊,即不同於真正意義上的引用操作。例如如下語句:

string str1 = "abcd";

string str2 = str1;

str2 = "efgh";// str1 is still "abcd" here

當對於一個新的string類型是原有對象引用的時候,這點和一般的引用類型一樣,但是當新的對象發生變化的時候,要重新分配一個新的地方,然后修改對象指向。

因此對於string操作的時候,尤其發生變化的時候,會顯得比較慢,因為其牽扯到內存地址的變化。(所以對於數據量比較大的字符操作時候,使用StringBuilder來說效率會提升很高。)

23. XmlSerializer使用的針對屬性的模式有什么好處?解決了什么問題?

這里的屬性指attribute。可以將不需要序列化的數據標記為[XmlIgnore],只序列化有用的數據,而不是序列化整個對象。可以省去沒有必要序列化的數據序列化工作,提升序列化時的性能。使用attribute還可以指導序列化的過程,以自定義生成xml文檔的格式。(11題對XmlSerializer有介紹)

24. 為什么不應該在.NET中使用out參數?它究竟好不好?

當想要一個函數產生多個輸出時,可以使用out參數返回函數的輸出值。這應該是out參數最大的作用。out參數的缺陷在於,它允許一個未初始化變量就在函數中作為out參數使用。這樣並不能保證在訪問一個作為out參數的變量時,它已經被初始化過,容易產生錯誤的結果。(個人觀點)

25. 特性能夠放到某個方法的參數上?如果可以,這有什么用?

可以,作用可以對參數有進一步限定,比如輸入參數為int類型,可以通過允許AttributeTargets=ParameterInfo的Attribute自定義實現來限定輸入參數的大小,比如當輸入參數小於100的時候便抱錯。

對方法的參數設置Attribute的例子: 
  [AttributeUsage(AttributeTargets.Parameter)] 
    public class ParameterAtt : Attribute 
    { 
        public int Min = 100; 
    }

public class AttributeTest 
    {       
        public void TestMethod([ParameterAtt(Min = 100)] int par1) 
        { 
            ParameterInfo para =

MethodInfo.GetCurrentMethod().GetParameters()[0]; 
            ParameterAtt att = ParameterAtt.GetCustomAttribute

(para, typeof(ParameterAtt)) as ParameterAtt; 
            if (att.Min > par1) 
            { 
                throw new Exception("要求para1最小為" + att.Min); 
            } 
        } 
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM