這段時間一邊忙工做,一邊在找新工做,面試過程當中不少基礎性的客觀題,我在實際工做中真的用的不多,學過或者看過的也忘的差很少了,不免對最簡單的問題產生一些迷惑,但願這篇帖子能給你們帶來一些幫助。這多是最最簡單,我以爲對我來講起碼面試前可能須要溫習一下,我比較緊張啦。。。。。。很差笑話我。
轉自:
http://bbs.51aspx.com/showtopic-2879.html
1.靜態變量和非靜態變量的區別?
2.const 和 static readonly 區別?
3.extern 是什麼意思?
4.abstract 是什麼意思?
5.internal 修飾符起什麼做用?
6.sealed 修飾符是幹什麼的?
7.override 和 overload 的區別?
8.什麼是索引指示器?
9.new 修飾符是起什麼做用?
10.this 關鍵字的含義?
11.可使用抽象函數重寫基類中的虛函數嗎?
12.密封類能夠有虛函數嗎?
13.若是基類中的虛屬性只有一個屬性訪問器,那麼繼承類重寫該屬性後能夠有幾個屬性訪問器?若是基類中有 get 和 set 兩個呢?
14.abstract 能夠和 virtual 一塊兒使用嗎?能夠和 override 一塊兒使用嗎?
15.接口能夠包含哪些成員?
16.類和結構的區別?
17.接口的多繼承會帶來哪些問題?
18.抽象類和接口的區別?
19.別名指示符是什麼?
20.如何釋放非託管資源?
21.P/Invoke是什麼?
22.StringBuilder 和 String 的區別?
23.explicit 和 implicit 的含義?
24.params 有什麼用?
25.什麼是反射?
參考答案(C# 語言範疇以內)
1.靜態變量和非靜態變量的區別?
答:
靜態變量:
靜態變量使用 static 修飾符進行聲明
在所屬類被裝載時建立
經過類進行訪問
所屬類的全部實例的同一靜態變量都是同一個值
非靜態變量:
不帶有 static 修飾符聲明的變量稱作非靜態變量
在類被實例化時建立
經過對象進行訪問
同一個類的不一樣實例的同一非靜態變量能夠是不一樣的值
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example01
{
class
Program
{
class
Class1
{
public
static
String staticStr
=
&
amp;quot;Class
&
amp;quot;;
public
String notstaticStr
=
&
amp;quot;Obj
&
amp;quot;;
}
static
void
Main(
string
[] args)
{
//
靜態變量經過類進行訪問,該類全部實例的同一靜態變量都是同一個值
Console.WriteLine(
&
amp;quot;Class1
'
s staticStr: {0}", Class1.staticStr);
Class1 tmpObj1
=
new
Class1();
tmpObj1.notstaticStr
=
&
amp;quot;tmpObj1
&
amp;quot;;
Class1 tmpObj2
=
new
Class1();
tmpObj2.notstaticStr
=
&
amp;quot;tmpObj2
&
amp;quot;;
//
非靜態變量經過對象進行訪問,不一樣對象的同一非靜態變量能夠有不一樣的值
Console.WriteLine(
&
amp;quot;tmpObj1
'
s notstaticStr: {0}", tmpObj1.notstaticStr);
Console.WriteLine(
&
amp;quot;tmpObj2
'
s notstaticStr: {0}", tmpObj2.notstaticStr);
Console.ReadLine();
}
}
}
結果:
Class1
'
s staticStr: Class
tmpObj1
'
s notstaticStr: tmpObj1
tmpObj2
'
s notstaticStr: tmpObj2
2.const 和 static readonly 區別?
答:
const
用 const 修飾符聲明的成員叫常量,是在編譯期初始化並嵌入到客戶端程序
static readonly
用 static readonly 修飾符聲明的成員依然是變量,只不過具備和常量相似的使用方法:經過類進行訪問、初始化後不能夠修改。但與常量不一樣的是這種變量是在運行期初始化
示例:
Code
測試類:
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example02Lib
{
public
class
Class1
{
public
const
String strConst
=
&
amp;quot;Const
&
amp;quot;;
public
static
readonly
String strStaticReadonly
=
&
amp;quot;StaticReadonly
&
amp;quot;;
//
public const String strConst = "Const Changed";
//
public static readonly String strStaticReadonly = "StaticReadonly Changed";
}
//
5-1-a-s-p-x
}
客戶端代碼:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
Example02Lib;
namespace
Example02
{
class
Program
{
static
void
Main(
string
[] args)
{
//
修改Example02中Class1的strConst初始值後,只編譯Example02Lib項目
//
而後到資源管理器裏把新編譯的Example02Lib.dll拷貝Example02.exe所在的目錄,執行Example02.exe
//
切不可在IDE裏直接調試運行由於這會從新編譯整個解決方案!!
//
能夠看到strConst的輸出沒有改變,而strStaticReadonly的輸出已經改變
//
代表Const變量是在編譯期初始化並嵌入到客戶端程序,而StaticReadonly是在運行時初始化的
Console.WriteLine(
&
amp;quot;strConst : {
0
}
&
amp;quot;, Class1.strConst);
Console.WriteLine(
&
amp;quot;strStaticReadonly : {
0
}
&
amp;quot;, Class1.strStaticReadonly);
Console.ReadLine();
}
}
}
結果:
strConst : Const
strStaticReadonly : StaticReadonly
修改後的示例:
測試類:
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example02Lib
{
public
class
Class1
{
//
public const String strConst = "Const";
//
public static readonly String strStaticReadonly = "StaticReadonly";
public
const
String strConst
=
&
amp;quot;Const Changed
&
amp;quot;;
public
static
readonly
String strStaticReadonly
=
&
amp;quot;StaticReadonly Changed
&
amp;quot;;
}
}
結果
strConst : Const
strStaticReadonly : StaticReadonly Changed
3.extern 是什麼意思?
答:
extern 修飾符用於聲明由程序集外部實現的成員函數
常常用於系統API函數的調用(經過 DllImport )。注意,和DllImport一塊兒使用時要加上 static 修飾符
也能夠用於對於同一程序集不一樣版本組件的調用(用 extern 聲明別名)
不能與 abstract 修飾符同時使用;
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Runtime.InteropServices;
namespace
Example03
{
class
Program
{
//
注意DllImport是一個Attribute Property,在System.Runtime.InteropServices命名空間中定義
//
extern與DllImport一塊兒使用時必須再加上一個static修飾符
[DllImport(
&
amp;quot;User32.dll
&
amp;quot;)]
public
static
extern
int
MessageBox(
int
Handle,
string
Message,
string
Caption,
int
Type);
static
int
Main()
{
string
myString;
Console.Write(
&
amp;quot;Enter your message:
&
amp;quot;);
myString
=
Console.ReadLine();
return
MessageBox(
0
, myString,
&
amp;quot;My Message Box
&
amp;quot;,
0
);
}
}
}
結果:
4.abstract 是什麼意思?
答:
abstract 修飾符能夠用於類、方法、屬性、事件和索引指示器(indexer),表示其爲抽象成員
abstract 不能夠和 static 、virtual 、override 一塊兒使用
聲明爲 abstract 成員能夠不包括實現代碼,但只有類中還有未實現的抽象成員,該類就不能夠被實例化,一般用於強制繼承類必須實現某一成員
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example04
{
#region
基類,抽象類
public
abstract
class
BaseClass
{
//
抽象屬性,同時具備get和set訪問器表示繼承類必須將該屬性實現爲可讀寫
public
abstract
String Attribute
{
get
;
set
;
}
//
抽象方法,傳入一個字符串參數無返回值
public
abstract
void
Function(String value);
//
抽象事件,類型爲系統預約義的代理(delegate):EventHandler
public
abstract
event
EventHandler Event;
//
抽象索引指示器,只具備get訪問器表示繼承類必須將該索引指示器實現爲只讀
public
abstract
Char
this
[
int
Index]
{
get
;
}
}
#endregion
#region
繼承類
public
class
DeriveClass : BaseClass
{
private
String attribute;
public
override
String Attribute
{
get
{
return
attribute;
}
set
{
attribute
=
value;
}
}
public
override
void
Function(String value)
{
attribute
=
value;
if
(Event
!=
null
)
{
Event(
this
,
new
EventArgs());
}
}
public
override
event
EventHandler Event;
public
override
Char
this
[
int
Index]
{
get
{
return
attribute[Index];
}
}
}
#endregion
class
Program
{
static
void
OnFunction(
object
sender, EventArgs e)
{
for
(
int
i
=
0
; i
<
((DeriveClass)sender).Attribute.Length; i
++
)
{
Console.WriteLine(((DeriveClass)sender));
}
}
static
void Main(string
[] args)
{
DeriveClass tmpObj =
new
DeriveClass();
tmpObj.Attribute =
&quot;1234567&
amp;quot;;
Console.WriteLine(tmpObj.Attribute);
//將靜態函數OnFunction與tmpObj對象的Event事件進行關聯
tmpObj.Event +=
new
EventHandler(OnFunction);
tmpObj.Function(&quot;7654321&
amp;quot;);
Console.ReadLine();
}
}
}
結果:
1234567
7
6
5
4
3
2
1
5.internal 修飾符起什麼做用?
答:
internal 關鍵字是類型和類型成員的訪問修飾符。只有在同一程序集的文件中,內部類型或成員纔是可訪問的
接口的成員不能使用 internal 修飾符;
應用場合:
內部訪問一般用於基於組件的開發,由於它使一組組件可以以私有方式進行合做,而沒必要嚮應用程序代碼的其他部分公開。例如,用於生成圖形用戶界面的框架能夠提供「控件」類和「窗體」類,這些類經過使用具備內部訪問能力的成員進行合做。因爲這些成員是內部的,它們不向正在使用框架的代碼公開。
示例
Code
程序集A (AssemblyA)
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
AssemblyA
{
public
class
ClassA
{
internal
string internalName =
" internal name"
;
public
string pubName =
" public name"
;
public
string
GetName()
{
return internalName +","+
pubName;
}
}
public
class
ClassB
{
public
string
GetName()
{
ClassA ca =
new
ClassA();
return ca.internalName +
ca.pubName;
}
}
}
程序集B (AssemblyB)
using
System;
using
System.Collections.Generic;
using
System.Text;
using
AssemblyA;
namespace
AssemblyB
{
public
class
ClassC
{
public
string
GetName()
{
ClassA ca =
new
ClassA();
string pubName = ca.pubName; //正確
string internalName = ca.internalName; //錯誤!!!!!! 不可訪問;
return
pubName;
}
}
}
6.sealed 修飾符是幹什麼的?
答:
sealed 修飾符表示密封
用於類時,表示該類不能再被繼承,不能和 abstract 同時使用,由於這兩個修飾符在含義上互相排斥
用於方法和屬性時,表示該方法或屬性不能再被繼承,必須和 override 關鍵字一塊兒使用,由於使用 sealed 修飾符的方法或屬性確定是基類中相應的虛成員
一般用於實現第三方類庫時不想被客戶端繼承,或用於沒有必要再繼承的類以防止濫用繼承形成層次結構體系混亂
恰當的利用 sealed 修飾符也能夠提升必定的運行效率,由於不用考慮繼承類會重寫該成員
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example06
{
class
Program
{
class
A
{
public
virtual
void
F()
{
Console.WriteLine(&quot;A.F&
amp;quot;);
}
public
virtual
void
G()
{
Console.WriteLine(&quot;A.G&
amp;quot;);
}
}
class
B : A
{
public
sealed
override
void
F()
{
Console.WriteLine(&quot;B.F&
amp;quot;);
}
public
override
void
G()
{
Console.WriteLine(&quot;B.G&
amp;quot;);
}
}
class
C : B
{
public
override
void
G()
{
Console.WriteLine(&quot;C.G&
amp;quot;);
}
}
static
void Main(string
[] args)
{
new
A().F();
new
A().G();
new
B().F();
new
B().G();
new
C().F();
new
C().G();
Console.ReadLine();
}
}
}
結果:
類 B 在繼承類 A 時能夠重寫兩個虛函數,如圖所示:
因爲類 B 中對 F 方法進行了密封, 類 C 在繼承類 B 時只能重寫一個函數,如圖所示:
控制檯輸出結果,類 C 的方法 F 只能是輸出 類B 中對該方法的實現:
A.F
A.G
B.F
B.G
B.F
C.G
7.override 和 overload 的區別?
答:
override 表示重寫,用於繼承類對基類中虛成員的實現
overload 表示重載,用於同一個類中同名方法不一樣參數(包括類型不一樣或個數不一樣)的實現
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example07
{
class
Program
{
class
BaseClass
{
public
virtual
void
F()
{
Console.WriteLine(&quot;BaseClass.F&
amp;quot;);
}
}
class
DeriveClass : BaseClass
{
public
override
void
F()
{
base
.F();
Console.WriteLine(&quot;DeriveClass.F&
amp;quot;);
}
public
void Add(int Left, int
Right)
{
Console.WriteLine(&quot;Add for Int: {0}&quot;, Left +
Right);
}
public
void Add(double Left, double
Right)
{
Console.WriteLine(&quot;Add for
int: {0}&quot;, Left +
Right);
}
}
static
void Main(string
[] args)
{
DeriveClass tmpObj =
new
DeriveClass();
tmpObj.F();
tmpObj.Add(1, 2
);
tmpObj.Add(1.1, 2.2
);
Console.ReadLine();
}
}
}
結果:
BaseClass.F
DeriveClass.F
Add for Int: 3
Add
for
int: 3.3
8.什麼是索引指示器?
答:
實現索引指示器(indexer)的類能夠象數組那樣使用其實例後的對象,但與數組不一樣的是索引指示器的參數類型不只限於int
簡單來講,其本質就是一個含參數屬性
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example08
{
public
class
Point
{
private
double
x, y;
public Point(double X, double
Y)
{
x =
X;
y =
Y;
}
//重寫ToString方法方便輸出
public
override
string
ToString()
{
return String.Format(&quot;X: {0} , Y: {1}&
amp;quot;, x, y);
}
}
public
class
Points
{
Point[] points;
public
Points(Point[] Points)
{
points =
Points;
}
public
int
PointNumber
{
get
{
return
points.Length;
}
}
//實現索引訪問器
public Point this[int
Index]
{
get
{
return
points[Index];
}
}
}
//感謝watson hua(http://huazhihao.cnblogs.com/
)的指點
//索引指示器的實質是含參屬性,參數並不僅限於int
class
WeatherOfWeek
{
public
string
this[int
Index]
{
get
{
//注意case段使用return直接返回因此不須要break
switch
(Index)
{
case
0
:
{
return
&quot;Today is cloudy!&
amp;quot;;
}
case
5
:
{
return
&quot;Today is thundershower!&
amp;quot;;
}
default
:
{
return
&quot;Today is fine!&
amp;quot;;
}
}
}
}
public
string
this[string
Day]
{
get
{
string TodayWeather =
null
;
//switch的標準寫法
switch
(Day)
{
case
&quot;Sunday&
amp;quot;:
{
TodayWeather =
&quot;Today is cloudy!&
amp;quot;;
break
;
}
case
&quot;Friday&
amp;quot;:
{
TodayWeather =
&quot;Today is thundershower!&
amp;quot;;
break
;
}
default
:
{
TodayWeather =
&quot;Today is fine!&
amp;quot;;
break
;
}
}
return
TodayWeather;
}
}
}
class
Program
{
static
void Main(string
[] args)
{
Point[] tmpPoints =
new Point[10
];
for (int i =
0; i < tmpPoints.Length; i++
)
{
tmpPoints =
new
Point(i, Math.Sin(i));
}
Points tmpObj =
new
Points(tmpPoints);
for (int i =
0; i < tmpObj.PointNumber; i++
)
{
Console.WriteLine(tmpObj);
}
string[] Week =
new
string[] { &quot;Sunday&quot;, &quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Staurday&
amp;quot;};
WeatherOfWeek tmpWeatherOfWeek =
new
WeatherOfWeek();
for (int i =
0; i <
6; i++
)
{
Console.WriteLine(tmpWeatherOfWeek);
}
foreach (string tmpDay in
Week)
{
Console.WriteLine(tmpWeatherOfWeek[tmpDay]);
}
Console.ReadLine();
}
}
}
結果:
X: 0 , Y: 0
X:
1 , Y: 0.841470984807897
X:
2 , Y: 0.909297426825682
X:
3 , Y: 0.141120008059867
X:
4 , Y: -0.756802495307928
X:
5 , Y: -0.958924274663138
X:
6 , Y: -0.279415498198926
X:
7 , Y: 0.656986598718789
X:
8 , Y: 0.989358246623382
X:
9 , Y: 0.412118485241757
Today
is cloudy!
Today
is fine!
Today
is fine!
Today
is fine!
Today
is fine!
Today
is thundershower!
Today
is cloudy!
Today
is fine!
Today
is fine!
Today
is fine!
Today
is fine!
Today
is thundershower!
Today
is fine!
9.new 修飾符是起什麼做用?
答:
new 修飾符與 new 操做符是兩個概念
new 修飾符用於聲明類或類的成員,表示隱藏了基類中同名的成員。而new 操做符用於實例化一個類型
new 修飾符只能用於繼承類,通常用於彌補基類設計的不足
new 修飾符和 override 修飾符不可同時用在一個成員上,由於這兩個修飾符在含義上互相排斥
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example09
{
class
BaseClass
{
//基類設計者聲明瞭一個PI的公共變量,方便進行運算
public
static
double PI =
3.1415
;
}
class
DervieClass : BaseClass
{
//繼承類發現該變量的值不能知足運算精度,因而能夠經過new修飾符顯示隱藏基類中的聲明
public
new
static
double PI =
3.1415926
;
}
class
Program
{
static
void Main(string
[] args)
{
Console.WriteLine(BaseClass.PI);
Console.WriteLine(DervieClass.PI);
Console.ReadLine();
}
}
}
結果:
3.1415
3.1415926
10.this 關鍵字的含義?
答:
this 是一個保留字,僅限於構造函數和方法成員中使用
在類的構造函數中出現表示對正在構造的對象自己的引用,在類的方法中出現表示對調用該方法的對象的引用,在結構的構造上函數中出現表示對正在構造的結構的引用,在結構的方法中出現表示對調用該方法的結果的引用
this 保留字不能用於靜態成員的實現裏,由於這時對象或結構並未實例化
在 C# 系統中,this 其實是一個常量,因此不能使用 this++ 這樣的運算
this 保留字通常用於限定同名的隱藏成員、將對象自己作爲參數、聲明索引訪問器、判斷傳入參數的對象是否爲自己
示例:
Code
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
Example10
{
class
Class1
{
private
double
c;
private
string
value;
public
double
C
{
get
{
return
c;
}
}
public Class1(double
c)
{
//限定同名的隱藏成員
this.c =
c;
}
public
Class1(Class1 value)
{
//用對象自己實例化本身沒有意義
if (this
!=
value)
{
c =
value.C;
}
}
public
override
string
ToString()
{
//將對象自己作爲參數
return
string.Format(&quot;{0} Celsius = {1} Fahrenheit&quot;, c, UnitTransClass.C2F(this
));
}
//因爲好奇,在這作了一個效率測試,想看看到底哪一種方式訪問成員變量更快,結論:區別不大。。。
public
string
Test1()
{
long vTickCount =
Environment.TickCount;
for (int i =
0; i <
10000000; i++
)
this.value =
i.ToString();
return
string.Format(&quot;Have this.: {0} MSEL&quot;, Environment.TickCount -
vTickCount);
}
public
string
Test2()
{
long vTickCount =
Environment.TickCount;
for (int i =
0; i <
10000000; i++
)
value =
i.ToString();
return
string.Format(&quot;Don't have this.: {0} MSEL", Environment.TickCount - vTickCount);
}
}
class
UnitTransClass
{
public
static
double
C2F(Class1 value)
{
//攝氏到華氏的轉換公式
return
1.8
* value.C +
32
;
}
}
class
Program
{
static
void Main(string
[] args)
{
Class1 tmpObj =
new Class1(37.5
);
Console.WriteLine(tmpObj);
Console.WriteLine(tmpObj.Test1());
Console.WriteLine(tmpObj.Test2());
Console.ReadLine();
}
}
}
結果:
37.5 Celsius =
99.5
Fahrenheit
Have this.: 4375
MSEL
Don't have this.: 4406 MSEL