C#基礎概念二十五問

iDotNetSpace發表於2008-09-19

1.靜態成員和非靜態成員的區別?

答:

靜態變數使用 static 修飾符進行宣告,在類被例項化時建立,通過類進行訪問

不帶有 static 修飾符宣告的變數稱做非靜態變數,在物件被例項化時建立,通過物件進行訪問

一個類的所有例項的同一靜態變數都是同一個值,同一個類的不同例項的同一非靜態變數可以是不同的值

靜態函式的實現裡不能使用非靜態成員,如非靜態變數、非靜態函式等

2.const 和 static readonly 區別?

答:

const

用 const 修飾符宣告的成員叫常量,是在編譯期初始化並嵌入到客戶端程式

static readonly

用 static readonly 修飾符宣告的成員依然是變數,只不過具有和常量類似的使用方法:通過類進行訪問、初始化後不可以修改。

但與常量不同的是這種變數是在執行期初始化

3.extern 是什麼意思?

答:

extern 修飾符用於宣告由程式集外部實現的成員函式

經常用於系統API函式的呼叫(通過 DllImport )。注意,和DllImport一起使用時要加上 static 修飾符

也可以用於對於同一程式集不同版本元件的呼叫(用 extern 宣告別名)

不能與 abstract 修飾符同時使用

4.abstract 是什麼意思?

答:

abstract 修飾符可以用於類、方法、屬性、事件和索引指示器(indexer),表示其為抽象成員

abstract 不可以和 static 、virtual 一起使用

宣告為 abstract 成員可以不包括實現程式碼,但只要類中還有未實現的抽象成員(即抽象類),那麼它的物件就不能被例項化,通常

用於強制繼承類必須實現某一成員

5.internal 修飾符起什麼作用?

答:

internal 修飾符可以用於型別或成員,使用該修飾符宣告的型別或成員只能在同一程集內訪問

介面的成員不能使用 internal 修飾符

值得注意的是,如果為 internal 成員加上了 protected 修飾符,這時的訪問級別為 internal 或 protected。只是看字面意思容

易弄錯,許多人認為 internal protected 應該是“只有同一個程式集中的子類可以訪問”,但其實它表示“同一個程式集中的所有

類,以及所有程式集中的子類都可以訪問”

6.sealed 修飾符是幹什麼的?

答:

sealed 修飾符表示密封

用於類時,表示該類不能再被繼承,不能和 abstract 同時使用,因為這兩個修飾符在含義上互相排斥

用於方法和屬性時,表示該方法或屬性不能再被重寫,必須和 override 關鍵字一起使用,因為使用 sealed 修飾符的方法或屬性肯

定是基類中相應的虛成員

通常用於實現第三方類庫時不想被客戶端繼承,或用於沒有必要再繼承的類以防止濫用繼承造成層次結構體系混亂

恰當的利用 sealed 修飾符也可以提高一定的執行效率,因為不用考慮繼承類會重寫該成員

7.override 和 overload 的區別?

答:

override 表示重寫,用於繼承類對基類中虛成員的實現

overload 表示過載,用於同一個類中同名方法不同引數(包括型別不同或個數不同)的實現

8.什麼是索引指示器?

答:

實現索引指示器(indexer)的類可以象陣列那樣使用其例項後的物件,但與陣列不同的是索引指示器的引數型別不僅限於int

簡單來說,其本質就是一個含引數屬性

9.new 修飾符是起什麼作用?

答:

new 修飾符與 new 操作符是兩個概念

new 修飾符用於宣告類或類的成員,表示隱藏了基類中同名的成員。而new 操作符用於例項化一個型別

new 修飾符只能用於繼承類,一般用於彌補基類設計的不足

new 修飾符和 override 修飾符不可同時用在一個成員上,因為這兩個修飾符在含義上互相排斥

10.this 關鍵字的含義?

答:

this 是一個保留字,僅限於建構函式和方法成員中使用

在類的建構函式中出現表示對正在構造的物件本身的引用,在類的方法中出現表示對呼叫該方法的物件的引用,在結構的構造上函式

中出現表示對正在構造的結構的引用,在結構的方法中出現表示對呼叫該方法的結果的引用

this 保留字不能用於靜態成員的實現裡,因為這時物件或結構並未例項化

在 C# 系統中,this 實際上是一個常量,所以不能使用 this++ 這樣的運算

this 保留字一般用於限定同名的隱藏成員、將物件本身做為引數、宣告索引訪問器、判斷傳入引數的物件是否為本身

11.可以使用抽象函式重寫基類中的虛擬函式嗎?

答:

可以


需使用 new 修飾符顯式宣告,表示隱藏了基類中該函式的實現

或增加 override 修飾符,表示抽象重寫了基類中該函式的實現

12.密封類可以有虛擬函式嗎?

答:

可以,基類中的虛擬函式將隱式的轉化為非虛擬函式,但密封類本身不能再增加新的虛擬函式

13.什麼是屬性訪問器?

答:

屬性訪問器(Property Accessor),包括 get 訪問器和 set 訪問器分別用於欄位的讀寫操作

其設計目的主要是為了實現物件導向(OO)中的封裝思想。根據該思想,欄位最好設為private,一個精巧的類最好不要直接把欄位

設為公有提供給客戶呼叫端直接訪問

另外要注意屬性本身並不一定和欄位相聯絡

14.abstract 可以和 virtual 一起使用嗎?可以和 override 一起使用嗎?

答:

abstract 修飾符不可以和 static、virtual 修飾符一起使用

abstract 修飾符可以和 override 一起使用,參見第11點

15.介面可以包含哪些成員?

答:

介面可以包含屬性、方法、索引指示器和事件,但不能包含常量、域、操作符、建構函式和解構函式,而且也不能包含任何靜態成員


16.類和結構的區別?

答:
類:

類是引用型別在堆上分配,類的例項進行賦值只是複製了引用,都指向同一段實際物件分配的記憶體

類有構造和解構函式

類可以繼承和被繼承

結構:

結構是值型別在棧上分配(雖然棧的訪問速度比較堆要快,但棧的資源有限放),結構的賦值將分配產生一個新的物件。

結構沒有建構函式,但可以新增。結構沒有解構函式

結構不可以繼承自另一個結構或被繼承,但和類一樣可以繼承自介面

17.介面的多繼承會帶來哪些問題?

答:

C# 中的介面與類不同,可以使用多繼承,即一個子介面可以有多個父介面。但如果兩個父成員具有同名的成員,就產生了二義性(

這也正是 C# 中類取消了多繼承的原因之一),這時在實現時最好使用顯式的宣告

18.抽象類和介面的區別?

答:

抽象類(abstract class)可以包含功能定義和實現,介面(interface)只能包含功能定義

抽象類是從一系列相關物件中抽象出來的概念, 因此反映的是事物的內部共性;介面是為了滿足外部呼叫而定義的一個功能約定,

因此反映的是事物的外部特性

分析物件,提煉內部共性形成抽象類,用以表示物件本質,即“是什麼”

為外部提供呼叫或功能需要擴充時優先使用介面

19.別名指示符是什麼?

答:

通過別名指示符我們可以為某個型別起一個別名

主要用於解決兩個名稱空間內有同名型別的衝突或避免使用冗餘的名稱空間

別名指示符在所有名稱空間最外層定義,作用域為整個單元檔案。如果定義在某個名稱空間內,那麼它只在直接隸屬的名稱空間內起

作用

20.如何手工釋放資源?

答:

 .NET 平臺在記憶體管理方面提供了GC(Garbage Collection),負責自動釋放託管資源和記憶體回收的工作。但在以下兩種情況需要我

們手工進行資源釋放:一、由於它無法對非託管資源進行釋放,所以我們必須自己提供方法來釋放物件內分配的非託管資源,比如你

在物件的實現程式碼中使用了一個COM物件;二、你的類在執行是會產生大量例項(象 GIS 中的Geometry),必須自己手工釋放這些資

源以提高程式的執行效率

最理想的辦法是通過實現一個介面顯式的提供給客戶呼叫端手工釋放物件,System 名稱空間內有一個 IDisposable 介面,拿來做這

事非常合適,省得我們自己再宣告一個介面了

21.P/Invoke是什麼?

答:

在受控程式碼與非受控程式碼進行互動時會產生一個事務(transition) ,這通常發生在使用平臺呼叫服務(Platform. Invocation

Services),即P/Invoke

如呼叫系統的 API 或與 COM 物件打交道,通過 System.Runtime.InteropServices 名稱空間

雖然使用 Interop 非常方便,但據估計每次呼叫事務都要執行 10 到 40 條指令,算起來開銷也不少,所以我們要儘量少呼叫事務

如果非用不可,建議本著一次呼叫執行多個動作,而不是多次呼叫每次只執行少量動作的原則

22.StringBuilder 和 String 的區別?

答:

String 在進行運算時(如賦值、拼接等)會產生一個新的例項,而 StringBuilder 則不會。所以在大量字串拼接或頻繁對某一字串進行操作時最好使用 StringBuilder,不要使用 String

另外,對於 String 我們不得不多說幾句:

1.它是引用型別,在堆上分配記憶體

2.運算時會產生一個新的例項

3.String 物件一旦生成不可改變(Immutable)


3.定義相等運算子(== 和 !=)是為了比較 String 物件(而不是引用)的值

23.explicit 和 implicit 的含義?

答:

explicit 和 implicit 屬於轉換運算子,如用這兩者可以讓我們自定義的型別支援相互交換

explicti 表示顯式轉換,如從 A -> B 必須進行強制型別轉換(B = (B)A)

implicit 表示隱式轉換,如從 B -> A 只需直接賦值(A = B)

隱式轉換可以讓我們的程式碼看上去更漂亮、更簡潔易懂,所以最好多使用 implicit 運算子。不過!如果物件本身在轉換時會損失一些資訊(如精度),那麼我們只能使用 explicit 運算子,以便在編譯期就能警告客戶呼叫端

24.params 有什麼用?

答:

params 關鍵字在方法成員的引數列表中使用,為該方法提供了引數個數可變的能力

它在只能出現一次並且不能在其後再有引數定義,之前可以

25.什麼是反射?

答:

反射,Reflection,通過它我們可以在執行時獲得各種資訊,如程式集、模組、型別、欄位、屬性、方法和事件

通過對型別動態例項化後,還可以對其執行操作

簡單來說就是用string可以在runtime為所欲為的東西,實際上就是一個.net framework內建的萬能工廠

一般用於外掛式框架程式和設計模式的實現,當然反射是一種手段可以充分發揮其能量來完成你想做的任何事情(前面好象見過一位高人用反射呼叫一個官方類庫中未說明的函式。。。)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-450314/,如需轉載,請註明出處,否則將追究法律責任。