不知道你看到這個題目會不會很郁悶,但這的确是一個很值得考慮的問題。
你當然會說,這有啥,代碼運作一下不就知道啦。
1

DateTime d = new DateTime();
編譯雖然通過,但我們要考慮一下,這個d目前是什麼值呢?
這就是一個很很值得考慮的問題。
我們知道,如果要聲明一個DateTime新執行個體初始化為指定的年、月和日
使用如下的代碼

DateTime d = new DateTime(2007,1,1);
那麼,按一般我們對類的設計方法,DateTime的預設構造函數傳回目前的日期執行個體比較合理。
但事實是

DateTime d = new DateTime();
2

System.Console.WriteLine(d);//0001-1-1 0:00:00
日期0001-1-1 0:00:00表示的是基督元年


3

System.Console.WriteLine(DateTime.MinValue);//0001-1-1 0:00:00
不過,事情到這裡還沒有結束,感覺上我們使用DateTime的預設構造函數産生了基督元年,但你去查一下DateTime的幫助,你會吓一跳,文檔上根本沒有聲明過DateTime的預設構造函數。
DateTime的構造函數重載為下表
<a>DateTime (Int64)</a>
<a>DateTime (Int64, DateTimeKind)</a>
<a>DateTime (Int32, Int32, Int32)</a>
<a>DateTime (Int32, Int32, Int32, Calendar)</a>
<a>DateTime (Int32, Int32, Int32, Int32, Int32, Int32)</a>
<a>DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Calendar)</a>
<a>DateTime (Int32, Int32, Int32, Int32, Int32, Int32, DateTimeKind)</a>
<a>DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32)</a>
<a>DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32, Calendar)</a>
<a>DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32, DateTimeKind)</a>
<a>DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32, Calendar, DateTimeKind)</a>
的的确确沒有預設構造函數,是不是寫文檔的人不仔細把預設構造函數忘記描述了呢?
當然不是這樣的,原因我們來逐漸分析
DateTime的定義為:public struct DateTime
我們看到DateTime不是class,而是我們沒有看到過的struct(結構)。
結構是一個和class非常接近的資料類型,我們來示範class和struct的差別
以下是對同一個現象描述的class和struct
struct常用來做一個輕量級的類,快速的配置設定和快速的銷毀,但這同時也失去了繼承等能力。是以如果你需要類的所有特性,就還是使用類更好。

public struct StockStruct
{
4
public string Name;
5
public string Code;
6
public double In;
7
public double Out;
8
9
}
10

11

public class StockClass
12
13
14
15
16
17
我們分别執行個體化,代碼的運作完全一樣

StockStruct ss = new StockStruct();

System.Console.WriteLine(ss.Name);

StockClass sc = new StockClass();

System.Console.WriteLine(sc.Name);
我們為這兩個資料類型添加預設構造函數

/*結構不能包含顯式的無參數構造函數
public StockStruct()
{
*/


public StockClass()
18
19
20
21
22
23
我們發現不能為struct添加顯式的無參數構造函數,這是為什麼呢?簡單的說,你可以這樣了解:
class預設沒有構造函數,當你一個構造函數都不寫得時候,編譯器會給你的類添加一個預設的構造函數。
struct天生有一個預設構造函數,該構造函數是由編譯器統一控制,是以你就不能再為結構編寫預設構造函數了。
我們再次修改我們的代碼

public StockStruct(string name,string code)
Name = name;
Code = code;


public StockClass(string name, string code)
24
25
26
27
以上代碼看似沒有什麼錯誤,但編譯的結構再次讓你感到沮喪。
class的代碼被編譯通過了,struct又有錯誤了
在控制離開構造函數之前,字段“StockStruct.In”必須完全指派
在控制離開構造函數之前,字段“StockStruct.Out”必須完全指派
該錯誤提示告訴我們,要麼我們不給struct編寫構造函數,編譯器使用各資料類型的預設值,如果我們編寫了構造函數,就必須在構造函數中為該struct的所有資料成員完全指派。
這其實就是值類型和引用類型的一個差別:
值類型,要求在編譯時知道對象的大小,引用類型可以推遲到運作時才知道對象的大小。
struct是值類型,是以又推導出另一個特征:struct沒有析構函數。

public struct StockStruct : Object
In = 0;
Out = 0;


public struct HKStock : StockStruct
{
上面的代碼又錯了,struct要求不能從其他類或結構繼承,其他結構和類也不允許繼承結構(結構天然的就是一個密封類型)。同時推導:struct 不能為 abstract,而應始終為隐式 sealed。
不過,結構僅可以支援接口,是以同時推導:結構成員無法聲明為protected。

public struct StockStruct : System.IComparable
public StockStruct(string name, string code)
public int CompareTo(object obj)
return -1;
結構可以包含構造函數、常量、字段、方法、屬性、索引器、運算符、事件和嵌套類型,但如果同時需要上述幾種成員,則應當考慮改為使用類作為類型。因為
本文轉自shyleoking 51CTO部落格,原文連結:http://blog.51cto.com/shyleoking/806257