c#數據類型和類型轉換


C# 數據類型

C# 中,變量分為以下幾種類型:

  • 值類型(Value types
  • 引用類型(Reference types
  • 指針類型(Pointer types

值類型(Value types

值類型變量可以直接分配給一個值。它們是從類 System.ValueType 中派生的。

值類型直接包含數據。比如 intcharfloat,它們分別存儲數字、字符、浮點數。當您聲明一個 int 類型時,系統分配內存來存儲值。

下表列出了 C# 2010 中可用的值類型:

 

 

如需得到一個類型或一個變量在特定平台上的准確尺寸,可以使用 sizeof 方法。表達式 sizeof(type) 產生以字節為單位存儲對象或類型的存儲尺寸。下面舉例獲取任何機器上 int 類型的存儲尺寸:

using System;

 

namespace DataTypeApplication

{

   class Program

   {

      static void Main(string[] args)

      {

         Console.WriteLine("Size of int: {0}", sizeof(int));

         Console.ReadLine();

      }

   }

}

當上面的代碼被編譯和執行時,它會產生下列結果:

Size of int: 4

引用類型(Reference types

引用類型不包含存儲在變量中的實際數據,但它們包含對變量的引用。

換句話說,它們指的是一個內存位置。使用多個變量時,引用類型可以指向一個內存位置。如果內存位置的數據是由一個變量改變的,其他變量會自動反映這種值的變化。內置的 引用類型有:objectdynamic  string

對象(Object)類型

對象(Object)類型 C# 通用類型系統(Common Type System - CTS)中所有數據類型的終極基類。Object System.Object 類的別名。所以對象(Object)類型可以被分配任何其他類型(值類型、引用類型、預定義類型或用戶自定義類型)的值。但是,在分配值之前,需要先進行類型轉換。

當一個值類型轉換為對象類型時,則被稱為 裝箱;另一方面,當一個對象類型轉換為值類型時,則被稱為 拆箱

object obj;

obj = 100; // 這是裝箱

動態(Dynamic)類型

您可以存儲任何類型的值在動態數據類型變量中。這些變量的類型檢查是在運行時發生的。

聲明動態類型的語法:

dynamic <variable_name> = value;

例如:

dynamic d = 20;

動態類型與對象類型相似,但是對象類型變量的類型檢查是在編譯時發生的,而動態類型變量的類型檢查是在運行時發生的。

字符串(String)類型

字符串(String)類型 允許您給變量分配任何字符串值。字符串(String)類型是 System.String 類的別名。它是從對象(Object)類型派生的。字符串(String)類型的值可以通過兩種形式進行分配:引號和 @引號。

例如:

String str = "csharp.com";

一個 @引號字符串:

@"csharp.com";

C# string 字符串的前面可以加 @(稱作"逐字字符串")將轉義字符(\)當作普通字符對待,比如:

string str = @"C:\Windows";

等價於:

string str = "C:\\Windows";

@ 字符串中可以任意換行,換行符及縮進空格都計算在字符串長度之內。

string str = @"<script type=""text/javascript"">

    <!--

    -->

</script>";

用戶自定義引用類型有:classinterface delegate

指針類型(Pointer types

指針類型變量存儲另一種類型的內存地址。C# 中的指針與 C C++ 中的指針有相同的功能。

聲明指針類型的語法:

type* identifier;

例如:

char* cptr;

int* iptr;

補充1

關於裝箱和拆箱

就像倉庫,倉庫里有貨架,貨架上有編號:A1,A2,A3...................., 這些編號就可以看做是引用類型,現在來了一批貨,有 土豆,黃瓜,西紅柿,這些就是值類型,如果你想讓 A1=土豆,那么就要把土豆搬到 A1 里面去,這就叫裝箱,裝箱需要耗費人力和工時(也就是耗費CPU和內存),同理拆箱就要把對應編號的貨物搬出來,也是需要耗費人力和工時。

裝箱:值類型轉換為對象類型, 實例:

int val = 8;

object obj = val;//整型數據轉換為了對象類型(裝箱)

拆箱:之前由值類型轉換而來的對象類型再轉回值類型, 實例:

int val = 8;

object obj = val;//先裝箱

int nval = intobj;//再拆箱

只有裝過箱的數據才能拆箱

 

補充2:

obj int之間關系

using System;

namespace RectangleApplication

{

    class ExecuteRectangle

    {

        static void Main(string[] args)

        {

            int a=9;

            object obj;

            obj = a;

            obj =10;

            Console.WriteLine("2: {0}", a);   // 輸出:2: 9

            Console.WriteLine("1: {0}", obj); // 輸出:1: 10

            Console.ReadLine();

        }

    }

} 

 

設置值 int a=9; obj=a; obj改變不會對 int a 進行改變,object 只是復制了 int a 的值出來然后對其操作而已。不會影響到 int 原來的值。

補充3

C# String string 的區別

string C# 中的類,String .net Framework 的類(C# IDE 中不會顯示藍色) C# string 映射為 .net Framework String 如果用 string, 編譯器會把它編譯成 String,所以如果直接用 String 就可以讓編譯器少做一點點工作。

如果使用 C#,建議使用 string,比較符合規范 string 始終代表 System.String(1.x) ::System.String(2.0) String 只有在前面有 using System;的時候並且當前命名空間中沒有名為 String 的類型(classstructdelegateenum)的時候才代表 System.String string 是關鍵字,String 不是,也就是說 string 不能作為類、結構、枚舉、字段、變量、方法、屬性的名稱,而 String 可以。

String CLR 的類型名稱(也算是關鍵字),而 string C# 中的關鍵字。string 在編譯時候 C# 編譯器會默認將其轉換為 String,在這里會多增加幾行轉換的代碼。很多時候都是建議使用 CLR 的類型而不要使用 C# 的類型(這是專家的建議)。比如說還有:使用 int 的時候最好使用 Int32 等。很多時候都是一個習慣問題,規范問題。還有一個不同就是在 VS 中表現的顏色不一樣:String 是綠色,string 是藍色。

補充4

關於值類型、引用類型以及的關系

值類型,聲明一個值類型的時候,是在中開辟一個內存空間來存放對應的值,當值類型的值發生改變的時候,則直接修改該內存空間所保存的值。例:

int n1 = 5;

int n2 = n1;

Console.WriteLine(n1 + "  "+ n2);    // 5  5

n2 = 7;

Console.WriteLine(n1 + "  " + n2)    // 5  7

 

這里首先在中開辟一個內存空間用來保存 n1 的值 5,接着再在中開辟一個新的內存空間用來保存 n2 的值 5,所以顯示出來的結果是 5 5。然后將 n2 中對應的內存空間保存的值修改成 7,故顯示出來的結果是 5 7

引用類型,聲明一個引用類型的時候,首先是在中開辟一個內存空間來存放對應的值,然后在中開辟一個內存空間用於保存在中開辟的內存空間的地址。當系統調用引用類型的時候,首先去中獲取到地址,然后根據地址在中找到對應的內存空間來獲取到對應值。像數組這樣的引用類型

string[] a1 = new string[]{ "a" , "b" , "c" };

string[] a2 = a1;

for(int i = 0; i < a2.Length; i++)

{

    Console.Write(a2[i] + " ");    //a b c

}

a1[2] = "d";

Console.WriteLine();            //換行

for(int i = 0; i < a2.Length; i++)

{

    Console.Write(a2[i] + " ");    //a b d

}

Console.WriteLine(); 

 

這里首先是在中開辟一個內存空間(假設:0X55)用來保存數組a1的值,然后在中開辟一個內存空間(a1)用於保存地址 0X55。當將 a1 賦給 a2 時,是將地址賦給 a2,即在中開辟一個內存空間(a2)用於保存地址 0X55,所以輸出 a2 的值是 a b c。當將 a1[2]修改成”d”的時候,修改的是0X55 內存空間保存的值,因為 a2 的地址和 a1 的地址一樣,所以輸出結果是 a b d

string 是一個特殊的引用類型,先看下面代碼:

string a = "123";

string b = a; 

Console.WriteLine(a+" "+b);  //123 123

string b = "456";

Console.WriteLine(a+" "+b);  //123 456

 

和數組類似的,這里首先在中開辟一個內存空間(假設:0X88)用來保存 a 的值 123,然后在中開辟一個內存空間(a)用於保存地址 0X88

和數組不同的是,當將 a 賦給 b 的時候,首先是在中開辟一個新的內存空間(假設:0X101)用於保存值 123,然后在中開辟一個內存空間(b)用於保存地址 0X101,所以輸出的結果是 123 123

當修改 b 值時,並不是修改0X101 內存空間的值,而是在中重新開辟一個新的內存空間(假設:0X210)用於保存 b 修改后的值,然后將 b 中對應的內存空間的所保存的地址修改成 0X210,所以輸出的結果是 123 456。而中的 0X101 內存空間將在下次的垃圾回收中被回收利用。

 

C# 類型轉換

類型轉換從根本上說是類型鑄造,或者說是把數據從一種類型轉換為另一種類型。在 C# 中,類型鑄造有兩種形式:

  • 隱式類型轉換 - 這些轉換是 C# 默認的以安全方式進行的轉換, 不會導致數據丟失。例如,從小的整數類型轉換為大的整數類型,從派生類轉換為基類。
  • 顯式類型轉換 - 顯式類型轉換,即強制類型轉換。顯式轉換需要強制轉換運算符,而且強制轉換會造成數據丟失。

下面的實例顯示了一個顯式的類型轉換:

實例

namespace TypeConversionApplication
{
    class ExplicitConversion
    {
        static void Main(string[] args)
        {
            double d = 5673.74;
            int i;

            // 強制轉換 double 為 int
            i = (int)d;
            Console.WriteLine(i);
            Console.ReadKey();
            
        }
    }
}

 

當上面的代碼被編譯和執行時,它會產生下列結果:

5673

C# 類型轉換方法

C# 提供了下列內置的類型轉換方法:

序號

方法 & 描述

1

ToBoolean
如果可能的話,把類型轉換為布爾型。

2

ToByte
把類型轉換為字節類型。

3

ToChar
如果可能的話,把類型轉換為單個 Unicode 字符類型。

4

ToDateTime
把類型(整數或字符串類型)轉換為 日期-時間 結構。

5

ToDecimal
把浮點型或整數類型轉換為十進制類型。

6

ToDouble
把類型轉換為雙精度浮點型。

7

ToInt16
把類型轉換為 16 位整數類型。

8

ToInt32
把類型轉換為 32 位整數類型。

9

ToInt64
把類型轉換為 64 位整數類型。

10

ToSbyte
把類型轉換為有符號字節類型。

11

ToSingle
把類型轉換為小浮點數類型。

12

ToString
把類型轉換為字符串類型。

13

ToType
把類型轉換為指定類型。

14

ToUInt16
把類型轉換為 16 位無符號整數類型。

15

ToUInt32
把類型轉換為 32 位無符號整數類型。

16

ToUInt64
把類型轉換為 64 位無符號整數類型。

下面的實例把不同值的類型轉換為字符串類型:

實例

namespace TypeConversionApplication
{
    class StringConversion
    {
        static void Main(string[] args)
        {
            int i = 75;
            float f = 53.005f;
            double d = 2345.7652;
            bool b = true;

            Console.WriteLine(i.ToString());
            Console.WriteLine(f.ToString());
            Console.WriteLine(d.ToString());
            Console.WriteLine(b.ToString());
            Console.ReadKey();
            
        }
    }
}

 

當上面的代碼被編譯和執行時,它會產生下列結果:

75

53.005

2345.7652

True

補充1

隱式轉換和顯式轉換

隱式轉換:C# 默認的以安全方式進行的轉換。本質是從小存儲容量數據類型自動轉換為大存儲容量數據類型,從派生類轉換為基類。

實例:

namespace TypeConvertion

{   class Class1

    {

 

    }

 

    class Class2 : Class1 //類Class2是類Class1的子類

    {

 

    }

    class Program

    {

        static void Main(string[] args)

        {

            int inum = 100;

            long lnum = inum; // 進行了隱式轉換,將 int 型(數據范圍小)數據轉換為了 long 型(數據范圍大)的數據

            Class1 c1 = new Class2(); // 這里也是隱式轉換,將一個新建的 Class2 實例轉換為了其基類 Class1 類型的實例 C1

        }

    }

}

 

顯式轉換:通過用戶使用預定義的函數顯式完成的,顯式轉換需要強制轉換運算符。

轉換類型的范圍大小和從屬關系和隱式轉換相反。顯式轉換可能會導致數據出錯,或者轉換失敗,甚至無法編譯成功。

實例:

double dnum = 100.1;

int ifromd = (int)dnum; //double類型顯式轉換轉為int類型

 

 

Class1 c11 = new Class1();

Class2 c22 = c11 as Class2; //使用as進行顯式轉換

Console.WriteLine(c22 is Class1);

Console.WriteLine(c22 is Class2);

 

運行結果:

FALSE

FALSE

is操作符:檢查對象是否與給定類型兼容。

as運算符:用於在兼容的引用類型之間執行轉換

as操作符類似於強制轉換,但又有區別,當對象為null時,不會拋異常而是會返回null

補充2

類型之間的轉換 - Convert Parse

string locstr = 123.ToString();

 

//如果要將"locstr"轉成整型數

 

//方法一: Convert

int i = Convert.ToInt16(locstr);

 

 

//方法二: Parse

int ii = int.Parse(locstr);

int.TryParse(string s,out int i)

 

該方式也是將數字內容的字符串轉換為int類型,但是該方式比int.Parse(string s) 好一些,它不會出現異常,最后一個參數result是輸出值,如果轉換成功則輸出相應的值,轉換失敗則輸出0

class test

{

    static void Main(string[] args)

    {

        string s1="abcd";

        string s2="1234";

        int a,b;

        bool bo1=int.TryParse(s1,out a);

        Console.WriteLine(s1+" "+bo1+" "+a);

        bool bo2=int.TryParse(s2,out b);

        Console.WriteLine(s2+" "+bo2+" "+b);

    }

}

 

結果輸出:

abcd False 0

1234 True 1234

補充3

C# 中對 double 類型的數據取整,可以使用 convert.toint32() 方法,也可使用 int 強制轉換為整數,使用 int 時並不存在四舍五入的情況,而是直接將后面的小數位數丟掉。比如:

class Program

{

    static void Main(string[] args)

    {

        double a = 1.35;

        double b = 1.65;

        int a1 = Convert.ToInt32(a);

        int a2 = (int)(a);

        int b1 = Convert.ToInt32(b);

        int b2 = (int)(b);

        Console.WriteLine("{0}使用convert方法轉化的結果為:{1}",a,a1);

        Console.WriteLine("{0}使用int強制轉換的結果為:{1}",a,a2);

        Console.WriteLine("{0}使用convert方法轉化的結果為:{1}", b, b1);

        Console.WriteLine("{0}使用int強制轉換的結果為:{1}", b, b2);

        Console.ReadKey();

    }

}

 

程序運行結果如下:

1.35使用convert方法轉化的結果為:1

1.35使用int強制轉換的結果為:1

1.65使用convert方法轉化的結果為:2

1.65使用int強制轉換的結果為:1

補充4

Convert.ToInt32() int.Parse() 的區別

沒搞清楚 Convert.ToInt32  int.Parse() 的細細微區別時千萬別亂用,否則可能會產生無法預料的結果,舉例來說:假如從 url 中取一個參數 page 的值,我們知道這個值是一個 int,所以即可以用 Convert.ToInt32(Request.QueryString["page"]),也可以用 int.Parse(Request.QueryString["page"]),但是如果 page 這個參數在 url 中不存在,那么前者將返回 00 可能是一個有效的值,所以你不知道 url 中原來根本就沒有這個參數而繼續進行下一下的處理,這就可能產生意想不到的效果,而用后一種辦法的話沒有 page 這個參數會拋出異常,我們可以捕獲異常然后再做相應的處理,比如提示用戶缺少參數,而不是把參數值當做 0 來處理。

(1) 這兩個方法的最大不同是它們對 null 值的處理方法: Convert.ToInt32(null) 會返回 0 而不會產生任何異常,但 int.Parse(null) 則會產生異常。

(2) 對數據進行四舍五入時候的區別

  • a. Convert.ToInt32(double value) 如果 value 為兩個整數中間的數字,則返回二者中的偶數;即 3.5 轉換為 44.5 轉換為 4,而 5.5 轉換為 6。不過 4.6 可以轉換為 54.4 轉換為 4
  • b. int.Parse("4.5") 直接報錯:"輸入字符串的格式不正確"

(3) 對被轉換類型的區別 int.Parse 是轉換 String int, Convert.ToInt32 是轉換繼承自 Object 的對象為 int (可以有很多其它類型的數據)。你得到一個 object 對象, 你想把它轉換為 int,  int.Parse 就不可以, 要用 Convert.ToInt32


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM