你是高級程序員?那就來挑戰一下!基礎題:
- 傳入某個屬性的set方法的隱含參數的名稱是什么? value,它的類型和屬性所聲名的類型相同。
- 如何在C#中實現繼承? 在類名后加上一個冒號,再加上基類的名稱。
- C#支持多重繼承么? 不支持。可以用接口來實現。
- 被PRotected修飾的屬性/方法在何處可以訪問? 在繼承或間接繼承與這個類的子類中可以訪問。
- 私有成員會被繼承么? 會,但是不能被訪問。所以看上去他們似乎是不能被繼承的,但實際上確實被繼承了。
- 請描述一下修飾符protected internal。 被protected internal修飾的屬性/方法只能在它的在同一個程序集(Assembly)中的子類被訪問。
- C#提供一個默認的無參數構造函數,當我實現了另外一個有一個參數的構造函數時候,還想保留這個無參數的構造函數。這樣我應該寫幾個構造函數? 兩個,一旦你實現了一個構造函數,C#就不會再提供默認的構造函數了,所以需要手動實現那個無參數構造函數。
- C#中所有對象共同的基類是什么? System.Object.
- 重載和覆寫有什么區別? 重載提供了對一個方法簽名的不同參數調用的實現。覆寫提供了子類中改變父類方法行為的實現。
- 在方法定義中,virtual有什么含意? 被virtual修飾的方法可以被子類覆寫。
- 能夠將非靜態的方法覆寫成靜態方法么? 不能,覆寫方法的簽名必須與被覆寫方法的簽名保持一致,除了將virtual改為override。
- 可以覆寫私有的虛方法么? 不可以,如果一個方法是虛方法,就不應該定義成私有的!
- 能夠阻止某一個類被其他類繼承么? 可以,使用關鍵字sealed。
- 能夠實現允許某個類被繼承,但不允許其中的某個方法被覆寫么? 可以,標記這個類為public,并標記這個方法為sealed。(注意:這個方法必須是覆蓋了父類中的一個虛方法,否則,無法使用sealed)
- 什么是抽象類(abstract class)? 一種不可以被實例化的類。抽象類中一般含有抽象方法,當然也可有具體實現。繼承類只有實現過所有抽象類的抽象方法后才能被實例化。
- 何時必須聲明一個類為抽象類? 當這個類中包含抽象方法時,或是該類并沒有完全實現父類的抽象方法時。
- 接口(interface)是什么? 只含有共有抽象方法(public abstract method)的類。這些方法必須在子類中被實現。
- 為什么不能指定接口中方法的修飾符? 接口中的方法用來定義對象之間通信的契約,指定接口中的方法為私有或保護沒有意義。他們默認為公有方法。
- 可以繼承多個接口么? 當然。
- 那么如果這些接口中有重復的方法名稱呢? 這種情況中你可以決定如何實現。當然需要特別得小心。但是在編譯環節是沒有問題的。
- 接口和抽象類的區別是什么? 接口中所有方法必須是抽象的,并且不能指定方法的訪問修飾符。抽象類中可以有方法的實現,也可以指定方法的訪問修飾符。
- 如何區別重載方法? 不同的參數類型,不同的參數個數,不同的參數順序。
- const和readonly有什么區別? const關鍵字用來聲明編譯時常量,readonly用來聲明運行時常量。
- System.String和System.StringBuilder有什么區別? System.String是不可變的字符串。System.StringBuilder存放了一個可變的字符串,并提供一些對這個字符串修改的方法。
高級題:
- Thread和Process之間有什么區別?.NET新引入了application Domain的概念,這樣他們三個之間有什么區別?引入了Application Domain會帶來一些潛在的問題么?
進程可以理解為一個容器,提供進程空間,線程所使用的內存都在進程空間中分配。每個線程有自己的堆棧。APPDomain相當于一個邏輯概念,相當于在進程中邏輯的劃分了一些區域,所以線程是可以跨域訪問另外的線程。
- Windows Service與普通的EXE在執行過程中有什么區別?
一般前者無界面,有windows的Service服務器負責維護啟動和關閉。Exe由用戶維護且一般有界面。
- 一個進程可以訪問的Windows地址空間有多大?等于系統的虛擬內存大小么?這兩方面將對系統的設計產生什么樣的影響?
a.跟數據總線有關系。一般32位操作系統,尋址空間可以達到4GB,所以一個進程可以訪問的地址也為4GB(不過實際上,有2GB是留給操作系統使用的,4M是不可訪問的,剩下的空間才供進程使用)。
b.不等于虛擬內存。
c.尋址空間和數據總線的寬度有關系。虛擬內存會消耗CPU處理時間。因為需要做內外存的轉換工作。
- EXE和DLL之間的區別是什么?在系統設計中應該如何選擇使用它們?
a..Exe有自己的進程空間,dll沒有,dll只能被引用后,和exe共享進程空間才能被調用和運行(其實還有rundll32命令可以啟動dll,該系統命令本質上就是為其提供進程空間)。
b.dll也叫動態鏈接庫,可以將反復使用的共有代碼和資源放在動態鏈接庫中,這樣在內存中只會有一個副本,節約內存空間(不同的進程根據不同的重定位信息可以定位到制定的dll中)。
- 普通的EXE與.NET EXE的執行過程有什么不同?
普通exe可以直接在操作系統上執行,但是.net exe需要jit的及時編譯,并在托管環境下(即CLR的控制下)運行
- 什么是弱類型,什么是強類型?在系統設計中應該首先考慮使用哪種類型?
弱類型在一定程度上允許不同類型的數據進行相互操作和運算,但是強類型不允許,因為強類型會做類型檢查工作。
- PDB文件是作什么用的?里面包含了什么信息?
程序數據庫(PDB)文件保存著調試和項目狀態信息,使用這些信息可以對程序的調試配置進行增量鏈接。
- Cyclomatic Complexity是什么?為什么它很重要?
圈復雜度,用于衡量程序的分支數量。一個正常的方法,分值應該控制在5,6個,如果分支數太大,則最好進行方法的分解,避免badsmell.
- 為創建一個critical section以訪問某個變量書寫一個標準的lock()并加上double check。
If(m_Instance!=null)
{
lock(this)
{
if(m_Instance!=null))
{
//do something
}
}
}
- 為某個對象實現標準的Dispose模式。
Class MyObject:Idisposable
{
public void Dispose()
{
//do something
}
}
就是實現Idisposable接口,進而實現自定的析構
- 什么是FullTrust?存在于GAC中的assembly擁有FullTrust么?
- 下面這個命令是做什么的?gacutil /l | find /i “system”
全局程序集緩存工具使您可以查看和操作全局程序集緩存和下載緩存的內容。
- 下面這個命令是作什么的?sn -t something.dll
Sn.exe提供用于密鑰管理、簽名生成和簽名驗證的選項。
- 跨防火墻的DCOM必須打開哪個端口?端口135是用來做什么的?
- 有什么辦法可以與現有unmanaged code集成?在集成的時候應該考慮什么問題?
- 簡要解釋一下OOP與SOA都是用來作什么的?
OOP是一種程序編程架構,包含幾個特征:組件,封裝,繼承,抽象,多態。
SOA叫面向服務架構。
- xmlSerializer是如何工作的?進程運行XmlSerializer時候需要什么樣的ACL權限?
ACL訪問控制列表。
- 在系統設計時,何時應該使用try catch?何時需要避免使用?
- Debug.Write()和Trace.Write()之間有什么區別?二者分別應該用于何處?
都是斷言。Debug.Write()為調試版本,在發行版本里面不會被執行,而Trace.Write在發行版本中會被執行。
- Debug Build和Release Build有什么區別?在執行效率上有什么明顯的區別么?
Debug build的版本包含了一些調試信息,執行效率會低一些。
- JIT是針對Assembly還是Method發生的?解釋一下為什么.NET的設計者要這樣做?
- 簡要描述一下GC的執行過程。
當內存減少到某個程度之后,CLR啟動垃圾回收,將那些不被引用的對象回收并釋放所占用的內存。
- 應該如何選擇使用abstract class還是interface?
抽象類可以有實現,接口無實現。接口可以多繼承,抽象類不行。
- 在設計一個自定義類型時應如何選擇使用Value Type還是Reference Type?
其實要描述的就是引用類型和值類型的區別。可以從內存分布和訪問效率兩方面談。
- 對于Value Type和Reference Type,a.Equals(b)的默認實現方式有什么不同?
值類型默認就是指是否相等。引用類型就是比較兩個引用是否指向同一個對象。
- .NET中為什么不提供默認的deep copy?如果需要,要如何實現deep copy?
因為深度拷貝涉及到拷貝的級數問題,就是需要深度拷貝到什么層次。在C#中,不可以直接覆寫MemberwiseClone方法,可以實現Iclone接口來實現自定義的深度拷貝。
- 相對于.NET 1.1,.NET2.0為了避免過度的boxing/unboxing造成的系統開銷提供了哪些支持?
范型。
- String是Value Type還是Reference Type?為什么.NET中的String對象被設置成immutable?
是引用類型。因為字符串對象在操作系統中出現的頻率很高,如果為每一個string都分配一個獨立的內存,將會是很大的系統開銷。所以string設置為不可變的,就是一種內存駐留技術,本質上就是讓同樣的字符串都訪問同一塊內存。比如:s1=”a”,s2=”b”,則s1和s2其實都是指向同一塊為”a”的內存;如果現在修改s1=”b”,則s1將不再指向”a”,而是開辟另一塊為”b”的內存空間,使s1指向b(其實如果有另一個s3=”b”,則s1就會和s3指向同一個”b”,此時s1不再重新開辟空間)。