C#是物件導向的語言,在物件導向的思想中,只有對象,所有事物都可以用類描述。所以比如這些,int,bool,char,string,double,long等都是類,那麼像,30,2.5,"test"都是對應類的一個對象。
static void Main(string[] args) { string istring = 30.ToString(); string dstring = 2.5.ToString(); string sstring = "test".ToString(); Console.WriteLine(string.Format("{0},{1},{2}", istring, dstring, sstring)); Console.ReadLine(); }
輸出:
可以看出它們有ToString()這個方法,所以它們是對象。
在平時寫代碼時,定義資料類型除了上述的這種之外,肯定都用過:
static void Main(string[] args) { Int32 i = 0; UInt32 j = 0; String str = "test"; Console.ReadLine(); }
這個其實是.NET的一個機制,.NET是一個平台,這個平台上有C#,VB這些語言。因此,.NET定義了一系列類型,映射到不同的語言中,Int32在c#中就是int。這樣的資料類型稱作基元類型,在C#中類的對象必須使用new產生。而這一部分類直接就可以用常量表示。基元類型定義在.net Framework中,System命名空間下。看一下基元類型在C#語言中的類型映射。
.NET Framework基元類型 |
C#類型 |
取值範圍 |
備忘 |
System.Boolean |
bool |
true/false |
/ |
System.Byte |
byte |
0 ~255 |
無符號8位整數 |
System.Sbyte |
sbyte |
-128 ~ 127 |
有符號8位整數 |
System.Char |
char |
0 ~ 65,535 |
無符號16位整數 |
System.Int16 |
short |
-32,768 ~ 32,767 |
有符號16位整數 |
System.UInt16 |
ushort |
0 ~ 65,535 |
無符號16位整數 |
System.Int32 |
int |
-2,147,483,648 ~ 2,147,483,647 |
有符號32位整數 |
System.Int64 |
long |
-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
有符號64位整數 |
System.UInt64 |
ulong |
0 ~ 18,446,744,073,709,551,615 |
無符號64位整數 |
System.Single |
float |
±1.5 × 10-45 ~ ±3.4 × 1038 (7位有效數字) |
32位單精確度浮點數 |
System.Double |
double |
±5.0 × 10-324 到 ±1.7 × 10308 (15至16位有效數字) |
64位雙精確度浮點 |
System.Decimal |
decimal |
±1.0 × 10-28 到 ±7.9 × 1028 (27至28位有效數字) |
128位浮點數數 |
System.String |
string |
任一字元串 |
/ |
System.UInt32 |
uint |
0 ~ 4,294,967,295 |
無符號32位整數 |
表中的除了string是參考型別(後面單獨解釋),其它都是實值型別。
下面簡單介紹下參考型別和實值型別。
學習C語言的時候有個堆和棧的概念。
堆區——程式員分配釋放,或者程式結束有OS回收,分配方式類似於鏈表。
棧區——由編譯器自動分配釋放,存放函數的參數值,變數值等。
棧記憶體結構可以快速的分配記憶體和回收記憶體,但棧空間有限,過多使用會“溢出”,因此棧只分配常用的,佔用空間小的資料類型;堆記憶體結構分配記憶體較慢,但是利用空間大,可以存放大型資料。
在C#中,基本上所有的資料都儲存在“堆”結構中,稱之為“託管堆”,受.NET記憶體回收監控。但是相對於棧堆結構中記憶體配置效率比較低。為了正確進行記憶體回收,每次分配的堆空間比實際所需空間稍大,小型資料使用堆是不太合適的。
可以比較看一下實值型別和參考型別:
C#中提供了Struct定義實值型別,直接在棧上分配記憶體。
/// <summary> /// 使用struct定義一個實值型別, /// 實值型別的只能實現介面,不能繼承類 /// </summary> public struct StructPositiveNumber : ICloneable { /// <summary> /// 實值型別欄位 /// </summary> private int number; /// <summary> /// 靜態唯讀欄位,作為類的初始值 /// </summary> public readonly static StructPositiveNumber InitialValue = new StructPositiveNumber(); /// <summary> /// 屬性 /// </summary> public int Number { get { return number; } set { if (value <= 0) { throw new Exception(); } this.number = value; } } /// <summary> /// 可以定義構造器,但是和類不同,這裡的預設構造器依然存在 /// </summary> public StructPositiveNumber(int value) { if (value <= 0) { throw new Exception(); } this.number = value; } /// <summary> /// 實現複製方法,返回當前對象 /// </summary> /// <returns></returns> public object Clone() { return new StructPositiveNumber(this.number); } }
調用
static void Main(string[] args) { //聲明變數,賦值 StructPositiveNumber pNumber1 = StructPositiveNumber.InitialValue; pNumber1.Number = 1; //pNumber1賦給pNumber2 StructPositiveNumber pNumber2 = pNumber1; //改變pNumber2的值 pNumber2.Number = 2; //看列印結果,改變了pNumber2的值,但是不影響pNumber1 Console.WriteLine(pNumber1.Number);//1 Console.WriteLine(pNumber2.Number);//2 //重新初始化pNumber2,通過構造器產生改變了初始值。 pNumber2 = new StructPositiveNumber(3); Console.WriteLine(pNumber2.Number);//3 //調用Clone將pNumber2複製給pNumber1 pNumber1 = (StructPositiveNumber)pNumber2.Clone(); Console.WriteLine(pNumber1.Number);//3 //改變pNumber1的值,但是pNumber2值不改變 pNumber1.Number = 4; Console.WriteLine(pNumber1.Number);//4 Console.WriteLine(pNumber2.Number);//3 Console.ReadLine(); }
結果
再看參考型別定義的:
public class ClassPositiveNumber : ICloneable { private int number; public int Number { get { return this.number; } set { if (value <= 0) { throw new Exception(); } this.number = value; } } //參考型別自己可以初始化為null,無需定義初始值 //public readonly static ClassPositiveNumber InitialValue = new ClassPositiveNumber(); public ClassPositiveNumber(int value) { if (value <= 0) { throw new Exception(); } this.number = value; } public object Clone() { return new ClassPositiveNumber(this.number); } }
調用
static void Main(string[] args) { ClassPositiveNumber cNumber1;//預設值為null cNumber1 = new ClassPositiveNumber(1); ClassPositiveNumber cNumber2 = cNumber1; cNumber2.Number = 2; //可以看出,兩個引用引用到了相同的對象 Console.WriteLine(cNumber1.Number);//2 Console.WriteLine(cNumber2.Number);//2 //重新初始化cNumber2,之前的對象已被丟棄 cNumber2 = new ClassPositiveNumber(3); Console.WriteLine(cNumber2.Number);//3 //複製是複製一個對象的副本,因此,是兩個不同的對象 cNumber1 = (ClassPositiveNumber)cNumber2.Clone(); Console.WriteLine(cNumber1.Number);//3 cNumber1.Number = 4; Console.WriteLine(cNumber1.Number);//4 Console.WriteLine(cNumber2.Number);//3 Console.ReadLine(); }
結果
通過例子,可以看出實值型別的特點如下:
a、使用struct聲明;
b、不能繼承類,但是可以實現介面(當然除object類外);
c、實值型別使用實值型別做為欄位,但是欄位無法有預設值;
c、實值型別中必須有預設構造器,而且自己定義構造器後,預設的無參數的構造器依然存在。而且在構造其中只能訪問類中的欄位,但是不能訪問屬性。符號=對於實值型別來說是賦值,所以賦值是實值型別變數不可為空,因為實值型別沒有引用的概念,肯定有值。
以上就是C#基礎知識整理:基礎知識(11) 實值型別,參考型別的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!