public struct Square
{
public double Side { get; }
public Square(double side)
{
Side = side;
}
}
public struct Circle
{
public double Radius { get; }
public Circle(double radius)
{
Radius = radius;
}
}
public struct Rectangle
{
public double Length { get; }
public double Height { get; }
public Rectangle(double length, double height)
{
Length = length;
Height = height;
}
}
public struct Triangle
{
public double Base { get; }
public double Height { get; }
public Triangle(double @base, double height)
{
Base = @base;
Height = height;
}
}
下面分别使用7之前的语法和7来写一个计算形状面积的方法。
is
类型模式表达式
在C# 7.0之前,我们需要使用if
和is
语句去判断类别:
public static double ComputeArea(object shape)
{
if (shape is Square)
{
var s = (Square)shape;
return s.Side * s.Side;
}
else if (shape is Circle)
{
var c = (Circle)shape;
return c.Radius * c.Radius * Math.PI;
}
// elided
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
在C# 7.0 中,通过使用is
表达式的扩展可以在类型判断成功的时候将其分配给一个变量,从而简化上面的代码:
public static double ComputeAreaModernIs(object shape)
{
if (shape is Square s)
return s.Side * s.Side; // s 只在这可用
else if (shape is Circle c)
return c.Radius * c.Radius * Math.PI; // c 只在这可用
else if (shape is Rectangle r)
return r.Height * r.Length; // r 只在这可用
// elided
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
新的is
表达式对值类型和引用类型都好使。
上面的例子中,变量s
、c
、r
只有在模式匹配表达式为true的时候才作用被分配。
通过switch语句使用模式匹配
之前switch
只支持常量模式。只能将变量和case
中的常量进行比较:
public static string GenerateMessage(params string[] parts)
{
switch (parts.Length)
{
case 0:
return "No elements to the input";
case 1:
return $"One element: {parts[0]}";
case 2:
return $"Two elements: {parts[0]}, {parts[1]}";
default:
return $"Many elements. Too many to write";
}
}
7之前switch
只支持常量模式。在C# 7.0 中没有这个限制了,可以通过switch
来使用类型模式:
public static double ComputeAreaModernSwitch(object shape)
{
switch (shape)
{
case Square s:
return s.Side * s.Side;
case Circle c:
return c.Radius * c.Radius * Math.PI;
case Rectangle r:
return r.Height * r.Length;
default:
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
}
在case
表达式中使用when
public static double ComputeArea_Version3(object shape)
{
switch (shape)
{
case Square s when s.Side == 0:
case Circle c when c.Radius == 0:
return 0;
case Square s:
return s.Side * s.Side;
case Circle c:
return c.Radius * c.Radius * Math.PI;
default:
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
}
在case
表达式中声明变量
static object CreateShape(string shapeDescription)
{
switch (shapeDescription)
{
case "circle":
return new Circle(2);
case "square":
return new Square(4);
case "large-circle":
return new Circle(12);
case var o when (o?.Trim()?.Length ?? 0) == 0:
// white space
return null;
default:
return "invalid shape description";
}
}