在變數中指定型別
- 宣告變數但不初始化
int i;
MyClass m;
- 宣告且初始化
int i=0;
MyClass m=new MyClass();
- 方法中引數與返回值指定型別
public int getValue(int i){
return i;
}
內建變數
C# 提供了一組標準的內建型別,這些型別可供在任何 C# 程式中使用。
- 基本變數
- 引用變數
在上表中,左側列中的每個 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");
}
}
通用型別系統
- 類是引用型別。
- 結構是值型別。
- 記錄型別可以是引用型別 (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';
- 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; }
- 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;