C#學習 [型別系統] 基本型別介紹(10)

huiy_小溪發表於2024-10-30

在變數中指定型別

  1. 宣告變數但不初始化
int i;
MyClass m;
  1. 宣告且初始化
int i=0;
MyClass m=new MyClass();
  1. 方法中引數與返回值指定型別
public int getValue(int i){
    return i;
}

內建變數

C# 提供了一組標準的內建型別,這些型別可供在任何 C# 程式中使用。

  1. 基本變數
    img
  2. 引用變數
    img

在上表中,左側列中的每個 C# 型別關鍵字(dynamic 除外)都是相應 .NET 型別的別名。 它們是可互換的。 例如,以下宣告宣告瞭相同型別的變數:

int a = 123;
System.Int32 b = 123;

自定義型別

可以使用 struct、class、interface、enum 和 record 構造來建立自己的自定義型別。

public class MyClass
{
    public static void Hello()
    {
        Console.WriteLine("hello from MyClass");
    }
}

通用型別系統

img

  • 類是引用型別。
  • 結構是值型別。
  • 記錄型別可以是引用型別 (record class) 或值型別 (record struct)。

值型別

值型別派生自System.ValueType(派生自 System.Object)。 派生自 System.ValueType 的型別在 CLR 中具有特殊行為。 值型別變數直接包含其值。 結構的記憶體在宣告變數的任何上下文中進行內聯分配。 對於值型別變數,沒有單獨的堆分配或垃圾回收開銷。 可以宣告屬於值型別的 record struct 型別,幷包括記錄的合成成員

值型別分為兩類:struct和enum。

內建的數值型別是結構,它們具有可訪問的欄位和方法:

// constant field on type byte.
byte b = byte.MaxValue;
byte num = 0xA;
int i = 5;
char c = 'Z';
  1. struct
public struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public override string ToString() => $"({X}, {Y})";
}

可以使用 readonly 修飾符來宣告結構型別為不可變。 readonly 結構的所有資料成員都必須是隻讀的,如下所示:
任何欄位宣告都必須具有 readonly 修飾符
任何屬性(包括自動實現的屬性)都必須是隻讀的,或者是 init 只讀的。 請注意,僅限 init 的資源庫從 C# 版本 9 開始可用。

public readonly struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; init; }
    public double Y { get; init; }

    public override string ToString() => $"({X}, {Y})";
}
public readonly double Sum()
{
    return X + Y;
}
public readonly override string ToString() => $"({X}, {Y})";
private int counter;
public int Counter
{
    readonly get => counter;
    set => counter = value;
}
public readonly double X { get; init; }
  1. enum

列舉定義的是一組已命名的整型常量。

public enum FileMode
{
    CreateNew = 1,
    Create = 2,
    Open = 3,
    OpenOrCreate = 4,
    Truncate = 5,
    Append = 6,
}

引用型別

定義為 class、record、delegate、陣列或 interface 的型別是 reference type,引用型別完全支援繼承。

在宣告變數 reference type 時,它將包含值 null,直到你將其分配給該型別的例項,或者使用 new 運算子建立一個。

MyClass myClass = new MyClass();
MyClass myClass2 = myClass;
MyClass myClass = new MyClass();

// Declare and assign using an existing value.
IMyInterface myInterface = myClass;

// Or create and assign a value in a single statement.
IMyInterface myInterface2 = new MyClass();

建立物件時,會在託管堆上分配記憶體。 變數只保留對物件位置的引用。

所有陣列都是引用型別,即使元素是值型別,也不例外

// Declare and initialize an array of integers.
int[] nums = { 1, 2, 3, 4, 5 };

// Access an instance property of System.Array.
int len = nums.Length;

文字值的型別

文字值從編譯器接收型別。

string s = "The answer is " + 5.ToString();
// Outputs: "The answer is 5"
Console.WriteLine(s);

Type type = 12345.GetType();
// Outputs: "System.Int32"
Console.WriteLine(type);

泛型型別

可使用一個或多個型別引數宣告的型別,用作實際型別(具體型別)的佔位符 。

List<string> stringList = new List<string>();
stringList.Add("String example");
// 下面程式碼會造成編譯錯誤:
stringList.Add(4);

透過使用型別引數,可重新使用相同類以儲存任意型別的元素,且無需將每個元素轉換為物件。

泛型集合類稱為強型別集合。

隱式型別本地變數

可宣告區域性變數而無需提供顯式型別。 var 關鍵字指示編譯器透過初始化語句右側的表示式推斷變數的型別。

// i is compiled as an int
var i = 5;

// s is compiled as a string
var s = "Hello";

// a is compiled as int[]
var a = new[] { 0, 1, 2 };

// expr is compiled as IEnumerable<Customer>
// or perhaps IQueryable<Customer>
var expr =
    from c in customers
    where c.City == "London"
    select c;

// anon is compiled as an anonymous type
var anon = new { Name = "Terry", Age = 34 };

// list is compiled as List<int>
var list = new List<int>();

**帶 var 關鍵字的隱式型別只能應用於本地方法範圍內的變數。 隱式型別不可用於類欄位。

指標型別(Pointer types)

指標型別變數儲存另一種型別的記憶體地址。C# 中的指標與 C 或 C++ 中的指標有相同的功能。

char* cptr;
int* iptr;

相關文章