C#7元祖和弃元,C#8索引和范围(数组切片),C#9记录类型
C#7元祖和弃元
/// <summary> /// 元组和弃元 /// </summary> internal class C7 { static (string, double, double) GetLocation() { var city = "西安市"; var lat = 33.42d; var lon = 107.40d; return (city, lon, lat); } public void Demo1() { //元组 (string Alpha, string Beta) namedLetters = ("a", "b"); Console.WriteLine($"{namedLetters.Alpha}, {namedLetters.Beta}"); //元组 (string city, double lon, double lat) = GetLocation(); Console.WriteLine($"{city},({lon},{lat})"); //弃元,在 C# 中可以使用下划线_来表示要舍弃的元,是为弃元,怎么样?你学会了吗? (string city1, _, _) = GetLocation(); Console.WriteLine($"{city1}"); } /// <summary> /// 我们可以将判断和赋值两个步骤合二为一: /// </summary> /// <param name="shape"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> public static double ComputeAreaModernIs(object shape) { if (shape is Square s) return s.Side * s.Side; else if (shape is Circle c) return c.Radius * c.Radius * Math.PI; else if (shape is Rectangle r) return r.Height * r.Length; // elided throw new ArgumentException( message: "shape is not a recognized shape", paramName: nameof(shape)); } /// <summary> /// 主要打破了传统 switch 语句的常量模式 /// </summary> /// <param name="shape"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> 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)); } } #region 引发表达式,这个主要是针对 throw 关键字的增强 //场景A:条件运算符 string arg = args.Length >= 1 ? args[0] : throw new ArgumentException("You must supply an argument"); //场景B:Null合并运算符 public string Name { get => name; set => name = value ?? throw new ArgumentNullException( paramName: nameof(value), message: "Name cannot be null"); } //场景C:Lambda表达式 DateTime ToDateTime(IFormatProvider provider) => throw new InvalidCastException("Conversion to a DateTime is not supported."); #endregion }
C#8数组切片
/// <summary>
/// 正序下标从零开始
/// 倒序下标从一开始
/// </summary>
public void Demo3()
{
// 正序下标从零开始
// 倒序下标从一开始
var words = new string[]
{
// index from start, index from end
"The", // 0, ^9
"quick", // 1, ^8
"brown", // 2, ^7
"fox", // 3, ^6
"jumped", // 4, ^5
"over", // 5, ^4
"the", // 6, ^3
"lazy", // 7, ^2
"dog" // 8, ^1
};
//取最后一个元素
Console.WriteLine($"The last word is {words[^1]}");//dog
//获取下标是一的元素到下标是三的元素
var quickBrownFox = words[1..4];
Console.WriteLine(quickBrownFox);//quick,brown,fox
//获取倒数第二个元素到倒数第一个元素
var lazyDog = words[^2..^0];
Console.WriteLine(lazyDog);//lazy,dog
//获取倒数第二个元素到结束
var lazyDog2 = words[^2..];
Console.WriteLine(lazyDog2);//lazy,dog
//获取全部元素
var all = words[..];
Console.WriteLine(all);
//获取开始到下标是四的元素
var firstPhrase = words[..4];
Console.WriteLine(firstPhrase);//The,quick,brown,fox
//获取下标是六的元素到结束
var lastPhrase = words[6..];
Console.WriteLine(lastPhrase);//the,lazy,dog
}
C#9记录类型
internal class C9
{
/// <summary>
/// 实体 通常都有一个唯一的标识并且在整个生命周期中具有连续性,这一类角色通过 class 来实现一直都工作得很好。
/// 例如,每一个 User 都会有一个唯一的UserId ,我们使用 UserId 来判断其相等性。
/// 而 值对象 则是指那些没有唯一的标识、不可变的、通过属性来判断相等性。
/// 例如,我们有一个地址 Address,它由省、市、区、县和详细地址组成,那么,问题来了,
/// 如果两个 Address 的省、市、区、县和详细地址都相同,这两个 Address 是不是同一个地址呢?
/// 常识告诉我们:不会,因为它们是不同的实例。
///
/// 这就是 record 出现的原因。
/// </summary>
record Address
{
public string Province { get; set; }
public string City { get; set; }
public string District { get; set; }
public string County { get; set; }
}
public record Person
{
public string LastName { get; }
public string FirstName { get; set; }
public Person(string first, string last) => (FirstName, LastName) = (first, last);
}
public void Demo()
{
var addr1 = new Address() { Province = "陕西省", City = "西安市", District = "雁塔区" };
var addr2 = new Address() { Province = "陕西省", City = "西安市", District = "雁塔区" };
Console.WriteLine($"addr1 == addr2:{addr1 == addr2}");// addr1 == addr2:True
var person = new Person("Bill", "Wagner");
Console.WriteLine(person);// Person { LastName = Wagner, FirstName = Bill }
Person brother = person with { FirstName = "Paul" }; // 修改FirstName的副本
Console.WriteLine(brother);// Person { LastName = Wagner, FirstName = Paul }
Person clone = person with { }; // 空集副本
Console.WriteLine(clone);// Person { LastName = Wagner, FirstName = Bill }
//模式匹配增强
object e;
if (e is not null)
{
// ...
}
}
// 模式匹配增强
public static bool IsLetter(this char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';
public static bool IsLetterOrSeparator(this char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '.' or ',';
}