开放的编程资料库

当前位置:我爱分享网 > C#教程 > 正文

C# 可空类型

C#可空类型教程展示了如何在C#中使用可空值。

null是一种独特的数据类型,表示缺少或不存在的值。NullReferenceException在尝试取消引用null对象引用时抛出。为了防止这些异常,我们付出了很多努力。

C#中的两种基本数据类型是值类型和引用类型。不能为值类型分配null文字。引用类型的默认值为null引用。

多年来,C#包含许多处理空值的功能。Null安全性是一组特定于可空类型的功能,有助于减少可能的NullReferenceException发生次数。

C#2.0引入了可空值类型。从那时起,可以使用T?语法将空值分配给值类型。

C#8.0引入了可为空的引用类型。使用可为空的引用类型,我们可以表达我们的意图,即引用类型可能为空或始终为非空。相同的T?语法表示引用类型可以为null。

可为空的上下文

可空上下文可以对编译器解释引用类型变量的方式进行细粒度控制。由于.NET6空状态分析和变量注释在新项目中默认启用。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

在项目级别,可空上下文是使用Nullable标记设置的。

#nullable enable

可以使用编译器指令将可空上下文的范围限定为C#文件。

C#可空值类型

可空值类型T?表示其基础值类型T的所有值和一个额外的空值。例如,bool?变量可以指定为truefalsenull之一。

T?System.Nullable结构的简写。HasValue返回一个值,指示当前System.Nullable是否具有其基础类型的有效值。Value从可空值类型中解压值。

可空值类型与值类型具有相同的赋值规则。方法中的局部变量必须在使用前赋值。默认情况下,类中的字段将具有空值。

C#可空示例

在下一个示例中,我们使用可为null的值类型。

Nullable<int> x = 0;
Console.WriteLine(x);

int? y = 0;
Console.WriteLine(y);

Console.WriteLine("-------------------------");

x = null;

if (x == null)
{
    Console.WriteLine("null value");
}

y = null;

if (y == null)
{
   Console.WriteLine("null value");
}

在示例中,我们创建了两个可为空的整数变量。首先将它们初始化为零,然后将它们分配为null

$ dotnet run
0
0
-------------------------
null value
null value

C#检查空值

我们可以使用!=isnot运算符来检查空值。

string?[] words = { "sky", "black", "rock", null, "rain", "cup" };

foreach (var word in words)
{
    if (word != null)
    {
        Console.WriteLine($"{word} has {word.Length} letters");
    }
}

Console.WriteLine("-------------------------");

foreach (var word in words)
{
    if (word is not null)
    {
        Console.WriteLine($"{word.ToUpper()}");
    }
}

我们有一个单词列表。为了防止NullReferenceExceptions,我们确保在调用元素的属性或方法之前每个值都不为null。

使用NullableHasValue属性,我们检查当前可为null的元素是否具有其基础类型的有效值。

int?[] vals = { 1, 2, 3, null, 4, 5 };

int sum = 0;

foreach (var e in vals)
{
    if (e.HasValue)
    {
        sum += e.Value;
    }
}

Console.WriteLine($"The sum is: {sum}");

在示例中,我们计算整数值的总和。

if (e.HasValue)
{
    sum += e.Value;
}

我们使用HasValue检查元素是否具有某些值,并通过Value解压该值。

C#空条件运算符

空条件运算符仅将成员访问?.或元素访问?[]操作应用于其操作数如果该操作数的计算结果为非空。如果操作数的计算结果为null,则应用该运算符的结果为null。

var users = new List<User>
{
    new User("John Doe", "gardener"),
    new User(null, null),
    new User("Lucia Newton", "teacher")
};

users.ForEach(user => Console.WriteLine(user.Name?.ToUpper()));

record User(string? Name, string? Occupation);

在示例中,我们有一个包含两个成员的用户记录:姓名职业。我们借助?.运算符访问对象的名称成员。

users.ForEach(user => Console.WriteLine(user.Name?.ToUpper()));

我们使用?.访问Name成员并调用ToUpper方法。?.通过不对null值调用ToUpper来防止System.NullReferenceException

?[]运算符允许将null值放入集合中。

int?[] vals = { 1, 2, 3, null, 4, 5 };

int i = 0;

while (i < vals.Length)
{
    Console.WriteLine(vals[i]?.GetType());
    i++;
}

我们在数组中有一个null值。我们通过对数组元素应用?.运算符来防止System.NullReferenceException

C#参数空异常

当将空引用传递给不接受它作为有效参数的方法时,将抛出ArgumentNullException

var words = new List<string?> { "falcon", null, "water", "war", "fly",
    "wood", "forest", "cloud", "wrath" };

foreach (var word in words)
{
    int n = 0;

    try
    {
        n = CountLtr(word, 'w');
        Console.WriteLine($"{word}: {n}");
    }
    catch (ArgumentNullException e)
    {
        Console.WriteLine($"{e.Message}");
    }
}

int CountLtr(string? word, char c)
{
    // if (word is null)
    // {
    //     throw new ArgumentNullException(nameof(word));
    // }

    ArgumentNullException.ThrowIfNull(word);

    return word.Count(e => e.Equals(c));
}

在示例中,我们抛出并捕获ArgumentNullException

$ dotnet run 
falcon: 0
Value cannot be null. (Parameter 'word')
water: 1
war: 1
fly: 0
wood: 1
forest: 0
cloud: 0
wrath: 1

C#null-forgiving运算符

在启用的可空上下文中,允许空值的运算符(!)会抑制编译器警告。运算符在运行时无效。它只影响编译器的静态流分析。

以下示例使用Playwright库;查看Playwright教程以获取更多信息。

using Microsoft.Playwright;
using System.Text;

using var pw = await Playwright.CreateAsync();
await using var browser = await pw.Chromium.LaunchAsync();

var page = await browser.NewPageAsync();

var ehds = new Dictionary<string, string>{ {"User-Agent", "C# program" } };
await page.SetExtraHTTPHeadersAsync(ehds);

var resp = await page.GotoAsync("http://webcode.me/ua.php");
var body = await resp!.BodyAsync();

Console.WriteLine(Encoding.UTF8.GetString(body));

在示例中,我们请求一个资源,该资源返回一个包含所使用的用户的响应。

var resp = await page.GotoAsync("http://webcode.me/ua.php");
var body = await resp!.BodyAsync();

当网站出现连接问题时,响应可能为空。但我们明确表示不担心这个问题。

C#空合并运算符

空合并运算符??返回其左手操作数的值(如果它不为空);否则,它计算右侧操作数并返回其结果。

var words = new List<string?> { "work", "falcon", null, "cloud", "forest" };

foreach (var word in words)
{
    var e = word ?? "null value";
    Console.WriteLine(e);
}

我们使用??运算符来打印“空值”而不是默认的空字符串。

C#空合并赋值运算符

空合并赋值运算符??=仅当左侧操作数赋值为null时,才将其右侧操作数的值分配给其左侧操作数。

List<int>? vals = null;

vals ??= new List<int> { 1, 2, 3, 4, 5 };

// if (vals == null)
// {
//     vals = new List<int> { 1, 2, 3, 4, 5 };
// }

vals.Add(6);
vals.Add(7);
vals.Add(8);

Console.WriteLine(string.Join(", ", vals));

vals ??= new List<int> { 1, 2, 3, 4, 5 };

Console.WriteLine(string.Join(", ", vals));

我们在整数值列表上使用空合并赋值运算符。不使用该运算符的等效代码已被注释掉。

List<int>? vals = null;

首先,列表被分配给null

vals ??= new List<int> { 1, 2, 3, 4, 5 };

我们使用??=为变量分配一个新的列表对象。由于它是null,因此列表已分配。

vals.Add(6);
vals.Add(7);
vals.Add(8);

Console.WriteLine(string.Join(", ", vals));

我们向列表中添加三个值并打印其内容。

vals ??= new List<int> { 1, 2, 3, 4, 5 };

我们尝试为变量分配一个新的列表对象。由于变量不再是null,因此不会分配列表。

$ dotnet run
1, 2, 3, 4, 5, 6, 7, 8
1, 2, 3, 4, 5, 6, 7, 8

C#string.IsNullOrWhiteSpace

IsNullOrWhiteSpace方法指示指定的字符串是null、空还是仅包含空白字符。

var words = new List<string?> { "\t", "falcon", "  ", null, "\n", "cloud", "" };

for (int i = 0; i < words.Count; i++)
{
    var e = words[i];

    if (string.IsNullOrWhiteSpace(e))
    {
        Console.WriteLine($"{i}: null or white space");
    } else
    {
        Console.WriteLine($"{i}: {e}");
    }
}

在示例中,我们对可空字符串元素列表使用了IsNullOrWhiteSpace方法。

$ dotnet run
0: null or white space
1: falcon
2: null or white space
3: null or white space
4: null or white space
5: cloud
6: null or white space

C#字符串.IsNullOrEmpty

IsNullOrEmpty方法指示指定的字符串是否为null或空字符串(“”)。

var words = new List<string?> { "\t", "falcon", "  ", null, "\n", "cloud", "" };

for (int i = 0; i < words.Count; i++)
{
    var e = words[i];

    if (string.IsNullOrEmpty(e))
    {
        Console.WriteLine($"{i}: null or empty");
    } else
    {
        Console.WriteLine($"{i}: {e}");
    }
}

在示例中,我们对可空字符串元素列表使用了IsNullOrEmpty方法。

$ dotnet run
0:
1: falcon
2:
3: null or empty
4:

5: cloud
6: null or empty

在本文中,我们使用了C#中的空值。

列出所有C#教程。

未经允许不得转载:我爱分享网 » C# 可空类型

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏