C# 可空类型(Nullable)
C# 可空类型(Nullable)
可空类型允许我们在值类型中包含 null 值,这在处理数据库查询结果或需要表示缺失值的情况时非常有用。
声明一个可空类型的语法如下:
< data_type>? <variable_name> = null;
其中 <data_type> 是基础的值类型,例如 int、bool 等,? 符号表示这是一个可空类型,<variable_name> 是变量名,= 后面的 null 表示初始时该可空类型变量的值为 null。
对于 Nullable<T> 类型,编译器会执行一些特殊的处理,使得我们可以将 null 赋值给值类型,而不会出现编译错误。同时,Nullable<T> 类型也提供了一些属性和方法来方便地处理可空类型的值,比如 HasValue 来判断是否有值,Value 来获取值,GetValueOrDefault() 来获取值或默认值等。
使用可空类型可以很好地应对实际应用中遇到的可能存在缺失值的情况,同时也可以简化对数据库等数据源的处理。
下面的实例演示了可空数据类型的用法:
using System;public class CalculatorApplication
{class NullablesAtShow{static void Main(string[] args){int? num1 = null;int? num2 = 45;double? num3 = new double?();double? num4 = 3.14157;bool? boolval = new bool?();// 显示值Console.WriteLine("显示可空类型的值: {0}, {1}, {2}, {3}",num1, num2, num3, num4);Console.WriteLine("一个可空的布尔值: {0}", boolval);Console.ReadLine();}}
}
当上面的代码被编译和执行时,它会产生下列结果:
显示可空类型的值: , 45, , 3.14157
一个可空的布尔值:
Null 合并运算符( ?? )
空合并运算符 ?? 是 C# 中的一个方便的操作符,用于简化处理可能为 null 的情况。它提供了一种简洁的方式来检查并提供默认值,以避免空引用异常。
表达式 a ?? b 表示,如果 a 不为 null,则结果为 a 的值;如果 a 为 null,则结果为 b 的值。
以下是空合并运算符的一些特点和用法:
- 当 a 不为 null 时,表达式的值为 a 的值。
- 当 a 为 null 时,表达式的值为 b 的值。
- a 和 b 的类型必须相同或兼容,否则会出现编译错误。
- 空合并运算符可以在任何具有可空类型或引用类型的情况下使用。
下面是一个简单的示例,演示了空合并运算符的使用:
using System;public class CalculatorApplication
{class NullablesAtShow{static void Main(string[] args){int? x = null;int y = x ?? 5; // 如果 x 不为 null,则 y 的值为 x 的值,否则为 5string name = null;string result = name ?? "Guest"; // 如果 name 不为 null,则 result 为 name 的值,否则为 "Guest"Console.WriteLine("y 的值: {0}", y);Console.WriteLine("result 的值: {0}", result);}}
}
当上面的代码被编译和执行时,它会产生下列结果:
y 的值: 5
result 的值: Guest
C# 数组(Array)
数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。
声明数组变量并不是声明 number0、number1、...、number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0]、numbers[1]、...、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。
所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素,最高的地址对应最后一个元素。
声明及初始化赋值数组
在 C# 中,声明数组需要指定数组的类型和名称,并可以选择指定数组的长度或初始化元素。
以下是几种常见的声明及初始化赋值数组的方式:
1、声明并初始化一个固定长度的数组:
int[] numbers = new int[5]; // 创建一个包含 5 个整数的数组
string[] names = new string[3]; // 创建一个包含 3 个字符串的数组
2、声明并初始化一个具有初始值的数组:
int[] numbers = new int[] { 1, 2, 3, 4, 5 }; // 创建一个包含 1、2、3、4 和 5 的整数数组
string[] names = new string[] { "Alice", "Bob", "Charlie" }; // 创建一个包含三个字符串的数组
3、使用简化的语法进行声明和初始化(仅适用于局部变量):
int[] numbers = { 1, 2, 3, 4, 5 }; // 类型推断,创建一个包含 1、2、3、4 和 5 的整数数组
string[] names = { "Alice", "Bob", "Charlie" }; // 类型推断,创建一个包含三个字符串的数组
在上述示例中,int[] 表示整数数组的类型,string[] 表示字符串数组的类型。使用 new 关键字创建一个新的数组实例,并指定数组的长度或初始化元素。
需要注意的是,数组的索引从 0 开始。可以通过索引来访问和修改数组中的元素,例如 numbers[0] 访问第一个元素,numbers[3] = 10 将第四个元素的值设置为 10。
下面是一个实例:
using System;class Program
{static void Main(){// 声明并初始化一个整数数组int[] numbers = new int[5] { 1, 2, 3, 4, 5 };// 声明并初始化一个字符串数组string[] names = new string[] { "Alice", "Bob", "Charlie" };// 使用简化的语法进行声明和初始化int[] otherNumbers = { 6, 7, 8, 9, 10 };string[] otherNames = { "Dave", "Eve", "Frank" };// 访问和修改数组中的元素Console.WriteLine("numbers[0]: " + numbers[0]); // 输出:1Console.WriteLine("names[1]: " + names[1]); // 输出:Bobnumbers[3] = 12; // 修改数组中的元素Console.WriteLine("numbers[3] 修改后: " + numbers[3]); // 输出:12// 遍历数组并输出所有元素Console.WriteLine("数字数组中的所有元素:");foreach (int number in numbers){Console.WriteLine(number);}Console.ReadLine();}
}
在上述示例中,我们创建了一个 Program 类,并在 Main 方法中进行了数组的声明、初始化和操作。首先,我们声明并初始化了两个数组 numbers 和 names,然后使用简化的语法声明并初始化了 otherNumbers 和 otherNames 数组。
接下来,我们展示了如何访问和修改数组中的元素。使用索引可以获取特定位置的元素的值,也可以修改元素的值。
最后,我们使用 foreach 循环(也可以使用 for 循环来访问每个数组元素)遍历数组并逐个输出所有元素。
多维数组
多维数组是数组的一种特殊形式,它允许在一个数组中存储多个维度的数据。在 C# 中,我们可以创建二维甚至更高维度的数组来表示表格、矩阵、立方体等数据结构。
声明和初始化多维数组
在 C# 中,可以使用以下语法来声明和初始化二维数组:
// 声明并初始化一个二维整数数组
int [,] matrix = new int [3,4] {{0, 1, 2, 3} , /* 初始化索引号为 0 的行 */{4, 5, 6, 7} , /* 初始化索引号为 1 的行 */{8, 9, 10, 11} /* 初始化索引号为 2 的行 */
};
上述代码中,我们声明了一个名为 matrix 的二维整数数组,它包含 3 行和 4 列。
访问和操作多维数组
可以使用索引来访问多维数组中的元素。对于二维数组,我们使用两个索引来表示行和列:
// 访问和修改二维数组中的元素
matrix[0, 0] = 1; // 设置第一行第一列的元素值为 1
int value = matrix[1, 2]; // 获取第二行第三列的元素值
代码示例
using System;class Program
{static void Main(){// 声明并初始化一个二维整数数组int[,] matrix = new int[3, 4];// 给数组赋值matrix[0, 0] = 1;matrix[0, 1] = 2;matrix[0, 2] = 3;matrix[0, 3] = 4;matrix[1, 0] = 5;matrix[1, 1] = 6;matrix[1, 2] = 7;matrix[1, 3] = 8;matrix[2, 0] = 9;matrix[2, 1] = 10;matrix[2, 2] = 11;matrix[2, 3] = 12;// 访问和输出二维数组中的元素Console.WriteLine("matrix[1, 2]: " + matrix[1, 2]); // 输出:7// 遍历二维数组并输出所有元素Console.WriteLine("矩阵阵列中的所有元素:");for (int i = 0; i < matrix.GetLength(0); i++){for (int j = 0; j < matrix.GetLength(1); j++){Console.Write(matrix[i, j] + " ");}Console.WriteLine();}Console.ReadLine();}
}
当上面的代码被编译和执行时,它会产生下列结果:
matrix[1, 2]: 7
矩阵阵列中的所有元素:
1 2 3 4
5 6 7 8
9 10 11 12
交错数组
交错数组(jagged array)是 C# 中的一种特殊数组形式,它允许在一个数组中存储其他数组作为其元素。与普通的多维数组不同,交错数组的各个维度的长度可以不同,因此它可以用来表示不规则的数据结构。
声明和初始化交错数组
在 C# 中,可以使用以下语法来声明和初始化一个交错数组:
// 声明并初始化一个交错数组
int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[] { 1, 2, 3 };
jaggedArray[1] = new int[] { 4, 5 };
jaggedArray[2] = new int[] { 6, 7, 8, 9 };
在上述示例中,我们声明并初始化了一个名为 jaggedArray 的交错数组。它包含了三个子数组,每个子数组的长度可以不同。
访问和操作交错数组
可以使用索引来访问交错数组中的元素,例如:
// 访问并输出交错数组中的元素
Console.WriteLine(jaggedArray[1][0]); // 输出:4
实例
using System;class Program
{static void Main(){// 声明并初始化一个交错数组int[][] jaggedArray = new int[3][];jaggedArray[0] = new int[] { 1, 2, 3 };jaggedArray[1] = new int[] { 4, 5 };jaggedArray[2] = new int[] { 6, 7, 8, 9 };// 访问并输出交错数组中的元素Console.WriteLine("jaggedArray[1][0]: " + jaggedArray[1][0]); // 输出:4// 遍历交错数组并输出所有元素Console.WriteLine("交错数组中的所有元素:");for (int i = 0; i < jaggedArray.Length; i++){for (int j = 0; j < jaggedArray[i].Length; j++){Console.Write(jaggedArray[i][j] + " ");}Console.WriteLine();}Console.ReadLine();}
}
在上述示例中,我们声明并初始化了一个名为 jaggedArray 的交错数组。然后,我们访问了交错数组中的特定元素,并使用嵌套的循环遍历了整个交错数组,并逐个输出了所有元素。
交错数组与二维数组的区别
-
维度不同:交错数组是由多个一维数组组成的数组,每个子数组的长度可以不同。而二维数组是一个由固定长度的一维数组组成的矩阵,每个一维数组具有相同的长度。
-
内存布局不同:交错数组的各个子数组在内存中是连续存储的,但各个子数组之间可能不连续。而二维数组是在内存中按矩阵布局连续存储的。
-
初始化方式不同:交错数组可以通过逐个初始化子数组来构建,每个子数组的长度可以根据需要动态设置。而二维数组需要在声明时指定每个维度的长度,并且无法在后续修改。
-
访问方式不同:由于内存布局不同,访问交错数组和二维数组的元素的方式也有所不同。对于交错数组,我们首先访问主数组的元素,然后再通过索引访问子数组的元素。而对于二维数组,我们可以直接通过两个索引访问元素,从而获得更直观的访问方式。