目录
C#中的模式匹配是一项通用功能,用于根据条件和类型测试表达式,通过不同C#版本中引入的各种模式类型,提供类型测试、可为null的类型检查、类型强制转换和高可读性等优点。本指南将通过每种类型的使用示例帮助您了解有关模式匹配类型的更多信息。
最后更新于2023年9月11日
C#中的模式匹配是一种功能,用于在测试表达式类型时测试某些条件的表达式。
通常,模式匹配是一种函数式编程功能,已经存在于其他流行语言中,例如Scala、Rust、Python、Haskell、Prolog和许多其他语言。
模式匹配是在C# 7中引入的,从那时起,它在随后的主要版本中收到了许多更新。
本指南将通过每种类型的使用示例帮助您了解有关模式匹配类型的更多信息。
请记住,您只能在“is”表达式或开关表达式中应用模式匹配。
C#语言中模式匹配的好处
- 型式测试
- 可为null的类型检查
- 类型转换和分配
- 高可读性
- 简明的语法
- 代码不那么复杂
因此,让我们从C#语言中不同类型的模式匹配开始
C# 7中
类型模式
表达式的类型测试:
public bool IsProductFood(object product)
{
return product is FoodModel;
}
声明模式
类型测试以及表达式成功匹配后对变量的赋值:
public bool IsProductFoodThatRequiresRefrigeration(object product)
{
return product is FoodModel food &&
RequiresRefrigeration(food.StorageTemperature);
}
常量模式
测试与常量值的比较,该常量值可以包括int、float、char、string、bool、enum字段,使用const,null。
public bool IsFreshProduce(FoodModel food)
{
return food?.Category?.ID is (int) ProductCategoryEnum.FreshProduce;
}
Null模式
检查引用类型或可为null类型是否为null。
public bool FoodDoesNotExist(FoodModel food)
{
return food is null;
}
Var模式
与类型模式类似,该var模式匹配表达式并检查null,并为变量赋值。
该var类型是根据匹配表达式的编译时类型声明的。
public bool IsProductFoodThatRequiresRefrigeration(FoodModel food)
{
return GetFoodStorageRequirements(food) is var storageRequirement &&
storageRequirement is StorageRequirementEnum.Freezer;
}
C# 8中
属性模式
它是一种高度可用的模式匹配类型,您可以在其中合并对象成员而不是变量来匹配给定条件。
它可以很容易地与其他模式匹配类型一起使用,例如相对模式、模式组合器和许多其他模式,以构建灵活而强大的逻辑表达式。
public bool IsOrganicFood(FoodModel food)
{
return food is
{
NonGMO: true,
NoChemicalFertilizers: true,
NoSyntheticPesticides: true
};
}
嵌套属性的用法在C# 8和C# 9中可用,但实现它不是最干净的解决方案或最简洁的语法。
丢弃模式
与discard运算符_的模式匹配匹配任何内容,包括null,它在新的开关表达式中大放异彩,以匹配默认值或else大小写。在下面的示例中,如果未提供食物的储存温度或数字与以下范围不匹配,则将引发自定义异常:
public int GetFoodStorageTemperature
(StorageRequirementEnum storageRequirement) => storageRequirement switch
{
StorageRequirementEnum.Freezer => -18,
StorageRequirementEnum.Refrigerator => 4,
StorageRequirementEnum.RoomTemperature => 25,
_ => throw new InvalidStorageRequirementException()
};
位置模式
主要与struct类型一起使用,利用类型的反构造器根据反构造器中的值位置匹配模式
请注意,我们还使用丢弃模式来忽略货币的价值,因为任何价值为零的东西,无论货币如何,都应该是自由的。
public bool IsFreeFood(FoodModel food)
{
return food.Price is (0, _);
}
元组模式
从位置模式的特殊派生,您可以在其中测试同一表达式中类型的多个属性:
public string GetFoodDescription(FoodModel food) => (food.NonGMO, food.Category.ID) switch
{
(true, (int)ProductCategoryEnum.FreshProduce) => "Non-GMO Fresh Product",
(true, (int)ProductCategoryEnum.Dairy) => "Non-GMO Dairy",
(false, (int)ProductCategoryEnum.Meats) => "GMO Meats. Avoid!",
(_, _) => "Invalid Food Group"
};
C# 9中
“增强”类型模式
您可以在开关表达式中执行类型检查,而无需对每种类型使用丢弃:
public string CheckValueType(object value) => value switch
{
int => "This is an integer number",
decimal => "This is a decimal number",
double => "This is a double number",
_ => throw new InvalidNumberException(value)
};
public class InvalidNumberException : Exception
{
public InvalidNumberException(object value) : base($"Invalid number {value}")
{ }
}
关系模式
在C# 9中引入的关系模式允许应用关系运算符> < >= <=来匹配模式与常量或enum值:
public StorageRequirementEnum
GetFoodStorageRequirements(FoodModel food) => food.StorageTemperature switch
{
<= -18 => StorageRequirementEnum.Freezer,
>= 2 and < 6 => StorageRequirementEnum.Refrigerator,
> 6 and < 30 => StorageRequirementEnum.RoomTemperature,
_ => throw new InvalidStorageRequirementException(food.StorageTemperature)
};
逻辑模式
这代表了否定、连词、析取的集合;不是,和,或分别。这些统称为模式组合器。
这些用于组合模式并对其应用逻辑条件:
public bool RequiresRefrigeration(ProductCategoryEnum productType)
{
return productType is ProductCategoryEnum.Dairy or ProductCategoryEnum.Meats;
}
否定空常量模式
检查表达式中是否存在非null值:
public bool BlogExists(BlogModel blog)
{
return blog is not null;
}
带括号的模式
这允许使用括号来控制执行顺序并将逻辑表达式组合在一起。它可以与任何类型的模式一起使用,但它的用法主要与模式组合器的使用有关:
public bool RequiresRefrigeration(int storageTemperature)
{
return storageTemperature is > 1 and (< 6);
}
C# 10中
扩展属性模式
在C# 10中,解决了嵌套属性匹配语法问题。
随着扩展属性模式的引入,在模式匹配中使用嵌套属性的语法现在变得简洁明了。
public bool RequiresRefrigeration(FoodModel food)
{
return food is
{
Category.ID: (int)ProductCategoryEnum.Dairy or
(int)ProductCategoryEnum.Meats
};
}
C# 11中
列表模式
列表匹配模式是C#中大量模式匹配的最新成员,使用列表模式,您可以将列表或数组与一组顺序元素进行匹配。
您可以将它与丢弃、模式组合器、范围、变量、类型赋值模式混合使用,以构建非常灵活和强大的列表模式匹配:
public (int?, int?) FindNumberOneAndNumberFour()
{
int[] numbers = { 1, 2, 3, 4, 5 };
// Match if 2nd value is anything, 3rd is greater than or equal 3, fifth is 5
if (numbers is [var numberOne, _, >= 3, int numberFour, 5])
{
return (numberOne, numberFour);
}
return (null, null);
}
太长;没读过
总结
近年来,C#获得了许多语言功能,以帮助开发人员在各种平台上构建可靠可靠的应用程序。
通过添加模式匹配功能,C#添加了强大的函数式编程功能,该功能已在多种编程语言中使用了数十年。
当然,您始终需要保持谨慎,不要过度使用模式匹配。
主要是,如果你正在与其他团队成员一起做一个大型项目,请记住,并不是每个人都知道部分或全部模式匹配功能,所以你不想突然引入太多这样的功能。
本文快速完整地概述了C#中添加的所有模式匹配类型。
如果您觉得它有用,如果您有任何意见,请告诉我。
引用
若要了解有关C#中的模式匹配的详细信息,可以查看以下参考资料:
本文最初发表于 Your Quick Guide to Pattern Matching in C# - Coding Sonata
https://www.codeproject.com/Articles/5368148/Your-Quick-Guide-to-Pattern-Matching-in-Csharp