重慶網(wǎng)站建設(shè)有限公司拼多多運(yùn)營
序號 | 系列文章 |
---|---|
0 | 【C#基礎(chǔ)】初識編程語言C# |
1 | 【C#基礎(chǔ)】C# 程序通用結(jié)構(gòu)總結(jié) |
2 | 【C#基礎(chǔ)】C# 程序基礎(chǔ)語法解析 |
文章目錄
- 前言
- 數(shù)據(jù)類型
- 一. 值類型(Value types)
- 二. 引用類型(Reference types)
- 三. 指針類型(Pointer types)
- 結(jié)語
前言
😄大家好,我是writer桑,前面一章已經(jīng)學(xué)習(xí)了C#的基礎(chǔ)語法,那本章就開始學(xué)習(xí)C#程序的數(shù)據(jù)類型,希望看完大家能夠有所收獲,感謝支持!
數(shù)據(jù)類型
C# 是一種強(qiáng)類型語言。 每個變量和常量都有一個類型,每個求值的表達(dá)式也是如此。每個方法聲明都為每個輸入?yún)?shù)和返回值指定名稱、類型和種類(值、引用或輸出)。C# 分別以值類型和引用類型作為類型的兩個主要類別。值類型的變量直接包含它們的數(shù)據(jù)。引用類型的變量存儲對數(shù)據(jù)(稱為“對象”)的引用。
一. 值類型(Value types)
值類型的變量包含類型的實(shí)例,不同于引用類型的變量包含對類型實(shí)例的引用。默認(rèn)情況下,在分配中,通過將實(shí)參傳遞給方法并返回方法結(jié)果來復(fù)制變量值。 對于值類型,每個變量都具有其自己的數(shù)據(jù)副本,對一個變量執(zhí)行的操作不會影響另一個變量(ref 和 out 參數(shù)變量除外)。
代碼理解:
using System;public struct MutablePoint
{public int X, Y;public MutablePoint(int x, int y) => (X, Y) = (x, y);public override string ToString() => $"({X}, {Y})";
}public class Program
{public static void Main(string[] args){var p1 = new MutablePoint(1, 2);var p2 = p1;Console.WriteLine($"{nameof(p1)} after {nameof(p2)} is modified:{p1} ");Console.WriteLine($"{nameof(p2)}: {p2}");MutateAndDisplay(p2);Console.WriteLine($"{nameof(p2)} after passing to a method: {p2}");}private static void MutateAndDisplay(MutablePoint p){p.X = 100;Console.WriteLine($"Point mutated in a method: {p}");}
}/*
* 預(yù)期的輸出:
* p1 after p2 is modified:(1, 2)
* p2: (1, 2)
* Point mutated in a method: (100, 2)
* p2 after passing to a method: (1, 2)
*/
- 從運(yùn)行結(jié)果可知 MutateAndDisplay 方法對傳入的參數(shù) p 的修改并不會影響 Main 方法中的 p2 參數(shù)。
- MutateAndDisplay 方法對值類型變量 p 的操作只影響當(dāng)前代碼所處的棧內(nèi)存的變量,而 Main 方法的 p2 變量和 p 變量又是兩個不同的變量。
- 結(jié)論:對值類型變量的操作只影響存儲在變量中的值類型實(shí)例。
下表列出了 C# 11 中值類型的簡單類型:
類型/關(guān)鍵字 | 描述 | 范圍 | 默認(rèn)值 | .NET類型 |
---|---|---|---|---|
bool | 布爾值 | True 或 False | False | System.Boolean |
char | 16位 Unicode 字符 | U+0000 到 U+FFFF | ‘\0’ | System.Char |
float | 32 位單精度浮點(diǎn)型 | ±1.5 x 10-45 至 ±3.4 x 1038 | 0.0F | System.Single |
double | 64 位雙精度浮點(diǎn)型 | ±5.0 × 10 -324 至±1.7 × 10308 | 0.0D | System.Double |
decimal | 128 位精確的十進(jìn)制值,28-29 有效位數(shù) | ±1.0 x 10-28 至7.9228 x 10^28 | 0.0M | System.Decimal |
sbyte | 8 位有符號整數(shù)類型 | -128 到 127 | 0 | System.SByte |
byte | 無符號的 8 位整數(shù) | 0 到 255 | 0 | System.Byte |
short | 有符號 16 位整數(shù) | -32,768 到 32,767 | 0 | System.Int16 |
ushort | 無符號 16 位整數(shù) | 0 到 65,535 | 0 | System.UInt16 |
int | 帶符號的 32 位整數(shù) | -2,147,483,648 到 2,147,483,647 | 0 | System.Int32 |
uint | 帶符號的 32 位整數(shù) | 0 到 4,294,967,295 | 0 | System.UInt32 |
long | 64 位帶符號整數(shù) | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 0L | System.Int64 |
ulong | 無符號 64 位整數(shù) | 0 到 18,446,744,073,709,551,615 | 0 | System.UInt64 |
nint | 帶符號的 32 位或 64位整數(shù) | 取決于(在運(yùn)行時(shí)計(jì)算的)平臺 | 0 | System.IntPtr |
nuint | 帶符號的 32 位或 64 位整數(shù) | 取決于(在運(yùn)行時(shí)計(jì)算的)平臺 | 0 | System.UIntPtr |
除了上述值類型的簡單類型之外,C# 程序還包括以下用關(guān)鍵字聲明的值類型種類:
- 枚舉類型(Enumeration)
枚舉類型是由基礎(chǔ)整型數(shù)值類型的一組命名常量定義的值類型。 C# 程序中使用 enum 關(guān)鍵字定義枚舉類型并指定枚舉成員的名稱,示例代碼如下:
enum Season
{Spring,Summer,Autumn,Winter
}
- 結(jié)構(gòu)類型(Structure)
結(jié)構(gòu)類型是是一種可封裝數(shù)據(jù)和相關(guān)功能的值類型,C# 程序中使用 struct 關(guān)鍵字定義結(jié)構(gòu)類型,示例代碼如下:
public struct MutablePoint
{public int X, Y;public MutablePoint(int x, int y) => (X, Y) = (x, y);public override string ToString() => $"({X}, {Y})";
}
- 元組類型(Tuple)
元組功能提供了簡潔的語法來將多個數(shù)據(jù)元素分組成一個輕型數(shù)據(jù)結(jié)構(gòu)。 下面的示例演示了如何聲明元組變量、對它進(jìn)行初始化并訪問其數(shù)據(jù)成員:
(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");
// Output:
// Tuple with elements 4.5 and 3.(double Sum, int Count) t2 = (4.5, 3);
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
// Output:
// Sum of 3 elements is 4.5.
- 可為空的值類型(Null)
可為 null 值類型 T?(T 表示泛型)表示其基礎(chǔ)值類型T 的所有值及額外的 null 值,示例代碼如下:
// 值類型可隱式轉(zhuǎn)換為相應(yīng)的可為空的值類型
double? pi = 3.14;
char? letter = 'a';int m2 = 10;
int? m = m2;bool? flag = null;// 可空值類型的數(shù)組:
int?[] arr = new int?[10];
一些針對值類型的常用操作:
- 若要在運(yùn)行時(shí)獲取本機(jī)大小的整數(shù)大小,可以使用 sizeof()。 但是,必須在不安全的上下文中編譯代碼。示例代碼:
Console.WriteLine($"size of nint = {sizeof(nint)}");
Console.WriteLine($"size of nuint = {sizeof(nuint)}");// 在64位進(jìn)程中運(yùn)行時(shí)輸出
//size of nint = 8
//size of nuint = 8// 在32位進(jìn)程中運(yùn)行時(shí)輸出
//size of nint = 4
//size of nuint = 4
- 若要在運(yùn)行時(shí)獲取本機(jī)大小的整數(shù)的最小值和最大值或者取值范圍,請將 MinValue 和 MaxValue用作值類型關(guān)鍵字的靜態(tài)屬性,示例代碼:
Console.WriteLine($"nint.MinValue = {nint.MinValue}");
Console.WriteLine($"nint.MaxValue = {nint.MaxValue}");//nint.MinValue = -9223372036854775808
//nint.MaxValue = 9223372036854775807
- 如果想在運(yùn)行時(shí)實(shí)現(xiàn)值類型數(shù)據(jù)之間的相互轉(zhuǎn)換,請使用隱式轉(zhuǎn)換或者顯式轉(zhuǎn)換,示例代碼:
// 隱式數(shù)據(jù)轉(zhuǎn)換舉例:int 轉(zhuǎn)換為 long
int a = 11;
long b = a; // 顯示數(shù)據(jù)轉(zhuǎn)換:long 轉(zhuǎn)換為 int
int a1 = 123;
long b1 = a;
int c = (int)b1;
- 如果想在運(yùn)行時(shí)輸出值類型的默認(rèn)值,可以使用 default 運(yùn)算符生成默認(rèn)類型值,例如:
Console.WriteLine(default(bool)); // False
- 如果想在運(yùn)行時(shí)輸出值類型數(shù)據(jù)的類型,可以使用 GetType 方法,例如:
bool b = false;
Console.WriteLine(b.GetType()); // System.Boolean
二. 引用類型(Reference types)
引用類型的變量存儲對其數(shù)據(jù)(對象)的引用,不同于值類型的變量直接包含其數(shù)據(jù)。 對于引用類型,多個變量可同時(shí)引用同一對象,多個變量之間互相傳遞的也是對這個對象的引用;因此,對一個變量執(zhí)行的操作會影響另一個變量所引用的對象(這點(diǎn)區(qū)別于值類型)。
代碼理解:
using System;// 類為引用類型
public class MutablePoint
{public int X, Y;public MutablePoint(int x, int y) => (X, Y) = (x, y);public override string ToString() => $"({X}, {Y})";
}public class Program
{public static void Main(string[] args){var p1 = new MutablePoint(1, 2);var p2 = p1;Console.WriteLine($"{nameof(p1)} after {nameof(p2)} is modified:{p1} ");Console.WriteLine($"{nameof(p2)}: {p2}");MutateAndDisplay(p2); // 顯示和改變 Console.WriteLine($"{nameof(p2)} after passing to a method: {p2}");}private static void MutateAndDisplay(MutablePoint p){p.X = 100;Console.WriteLine($"Point mutated in a method: {p}");}
}/*
* 預(yù)期的輸出:
* p1 after p2 is modified:(1, 2)
* p2: (1, 2)
* Point mutated in a method: (100, 2)
* p2 after passing to a method: (100, 2)
*/
- 從輸出結(jié)果可知 MutateAndDisplay 方法對參數(shù) p 修改的同時(shí)也修改了 Main 方法中的 p2 參數(shù)。
- 因?yàn)?p2 變量和 p 變量都是引用同一個對象 MutablePoint 類,也就是指向了同一塊內(nèi)存地址,所以 p2 變量對這內(nèi)存進(jìn)行修改的同時(shí)也修改了 p 變量的內(nèi)存,兩者同時(shí)發(fā)生變化。
- 結(jié)論:當(dāng)兩個變量引用同一個對象時(shí),一個變量執(zhí)行的操作會影響另一個變量的運(yùn)行結(jié)果。
以下表格列舉出了 C# 內(nèi)置引用類型:
類型/關(guān)鍵字 | 描述 | .NET 類型 |
---|---|---|
object | 對象類型 | System.Object |
string | 字符串類型 | System.String |
dynamic | 動態(tài)類型 | System.Object |
除了上述內(nèi)置的引用類型之外,C# 程序還包括以下用關(guān)鍵字聲明的引用類型:
- 記錄類型(Record)
從 C# 9 開始,可以使用 record 關(guān)鍵字定義一個 record 類型,用來提供用于封裝數(shù)據(jù)的內(nèi)置功能,record 類型用來構(gòu)建不可變類型和和線程安全對象,簡單的示例:
// 聲明 record class 引用類型:
public record Person
{public string FirstName { get; init; } = default!;public string LastName { get; init; } = default!;
};// 聲明 record struct 值類型:
public record struct Point
{public double X { get; init; }public double Y { get; init; }
}
- 類類型(Class)
類是將同類對象的共同屬性和行為抽象出來形成的一個相對復(fù)雜的數(shù)據(jù)類型,在 C# 程序中使用 class 關(guān)鍵字聲明類,示例如下:
class TestClass
{//方法,屬性,字段,事件,委托//和嵌套類到這里。
}
- 接口類型(Interface)
接口定義"協(xié)定",繼承接口的類或結(jié)構(gòu)體都必須實(shí)現(xiàn)接口中所定義的成員,在 C# 編程中使用 interface 關(guān)鍵字定義接口,示例如下:
// 定義接口 ISampleInterface
interface ISampleInterface
{void SampleMethod();
}// 類 Program 繼承接口并實(shí)現(xiàn)
public class Program : ISampleInterface
{public void SampleMethod(){throw new NotImplementedException();}
}
- 可為空的引用類型(Null)
引用類型 T? 的變量也可以用 null 進(jìn)行初始化,注意在取消引用之前必須檢查變量是否為空, 示例如下:
string notNull = "Hello";
string? nullable = default;
notNull = nullable!; // 給定為空值
一些針對引用類型的常用操作:
- 當(dāng)一個值類型轉(zhuǎn)換為對象類型時(shí),則被稱為裝箱;相對的,當(dāng)一個對象類型轉(zhuǎn)換為值類型時(shí),則被稱為拆箱,示例代碼:
//將整型變量i進(jìn)行了裝箱并分配給對象o。
int i = 123;
object o = i;// 將對象o拆箱并分配給對象i;
i = (int)o;Console.WriteLine(i); // 123
- string 字符串類型常見的相等運(yùn)算、連接操作、輸出指定位置的字符,示例代碼:
string s1 = "hello, world";
string s2 = "hello, C#";// 定義相等運(yùn)算符 == 和 != 比較 string 對象之間是否相等:
Console.WriteLine(s1 == s2); // False // 定義 + 連接運(yùn)算符連接兩個字符串:
Console.WriteLine(s1 + s2); // hello, worldhello, C# // 定義 [] 運(yùn)算符可訪問字符串指定位置的字符:
Console.WriteLine(s1[0]); // h
- dynamic 類型的變量表示不在編譯期間進(jìn)行類型檢查, 而是在運(yùn)行期間再進(jìn)行解析,示例如下:
dynamic d = 20; // 運(yùn)行時(shí)進(jìn)行類型檢查
三. 指針類型(Pointer types)
C# 程序中在不安全的上下文中,類型除了是值類型或引用類型外,還可以是指針類型 , 通過指針類型可以直接操作對象的內(nèi)存,指針類型聲明采用下列形式之一:
//type* identifier;
void* identifier; // 允許但不建議 // 又例如:
char* cptr;
int* iptr;
- 指針類型不能從對象繼承,并且指針類型之間不存在類型轉(zhuǎn)換
- 指針類型不支持類型裝箱和拆箱的操作
- 指針不能指向引用或包含引用的結(jié)構(gòu),因?yàn)闊o法對對象引用進(jìn)行垃圾回收
- MyType* 類型的指針變量的值為 MyType 類型的變量的地址
(ps:指針類型不在本章進(jìn)行詳細(xì)的討論。)
結(jié)語
?? 以上就是 C# 數(shù)據(jù)類型的介紹,希望能夠?qū)Υ蠹矣兴鶐椭?。望大家多多支?#xff0c;你們的支持就是筆者創(chuàng)作最大的動力!