C#7元祖和弃元,C#8索引和范围(数组切片),C#9记录类型
C#7元祖和弃元
////// 元组和弃元 /// 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}"); } /// /// 我们可以将判断和赋值两个步骤合二为一: /// /// /// /// 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)); } /// /// 主要打破了传统 switch 语句的常量模式 /// /// /// /// 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数组切片
////// 正序下标从零开始 /// 倒序下标从一开始 /// 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
{
///
/// 实体 通常都有一个唯一的标识并且在整个生命周期中具有连续性,这一类角色通过 class 来实现一直都工作得很好。
/// 例如,每一个 User 都会有一个唯一的UserId ,我们使用 UserId 来判断其相等性。
/// 而 值对象 则是指那些没有唯一的标识、不可变的、通过属性来判断相等性。
/// 例如,我们有一个地址 Address,它由省、市、区、县和详细地址组成,那么,问题来了,
/// 如果两个 Address 的省、市、区、县和详细地址都相同,这两个 Address 是不是同一个地址呢?
/// 常识告诉我们:不会,因为它们是不同的实例。
///
/// 这就是 record 出现的原因。
///
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 ',';
}