diff --git a/samples/CS9/Program.cs b/samples/CS9/Program.cs index 151f2a2..8124b8a 100644 --- a/samples/CS9/Program.cs +++ b/samples/CS9/Program.cs @@ -1,34 +1,39 @@ // ReSharper disable All -namespace CS9 { - class Program { +namespace CS9 +{ + class Program + { // Relational patterns (>= operator et al.) + // Logical patterns ("or", also "and" and "not") // Note: parens ( and ) can be used to determine precedence bool IsPastMidYear(DateTime dt) => dt is { Month: >= 7 }; + bool IsThisYearOrLast(DateTime dt) => dt is { Year: 2022 or 2021 }; - bool IsSummer(DateTime dt) => dt is - { Month: 7 or 8 } or - { Month: 6, Day: >= 21 } or - { Month: 9, Day: < 21 }; + bool IsSummer(DateTime dt) => + dt is { Month: 7 or 8 } or { Month: 6, Day: >= 21 } or { Month: 9, Day: < 21 }; // Class with "Deconstruct" implementation - class Order { + class Order + { public int ItemCount { get; set; } public double ItemPrice { get; set; } - public void Deconstruct(out int itemCount, out double itemPrice) { + public void Deconstruct(out int itemCount, out double itemPrice) + { itemCount = ItemCount; itemPrice = ItemPrice; } } - public enum OrderValue { + public enum OrderValue + { ValuableDueToHighCount, ValuableDueToHighItemPrice, ValuableDueToHighTotal, - NotValuable + NotValuable, } // Positional patterns with "discard" placeholders - note that @@ -38,7 +43,9 @@ namespace CS9 { { // Labels are optional here but can be useful // for readability - Order (itemCount: < 0, itemPrice: _) => throw new ArgumentException("Positive itemCounts please!"), + Order(itemCount: < 0, itemPrice: _) => throw new ArgumentException( + "Positive itemCounts please!" + ), (_, < 0) => throw new ArgumentException("Positive itemPrices please!"), (>= 100, _) => OrderValue.ValuableDueToHighCount, (_, >= 1000) => OrderValue.ValuableDueToHighItemPrice, @@ -46,10 +53,58 @@ namespace CS9 { // Assign variable names for further processing var (c, p) when c * p > 1000 => OrderValue.ValuableDueToHighTotal, - _ => OrderValue.NotValuable + _ => OrderValue.NotValuable, }; - static void Main(string[] args) { + static void Main(string[] args) + { + var order = new Order { ItemCount = 30, ItemPrice = 50 }; + // Let's see if this order is valuable + var category = OrderValueCategory(order); + Console.WriteLine($"This order is categorized as: {category}"); + + // Let's see that linked list + LinkedList list = new LinkedList.Node( + 1, + new LinkedList.Node(2, new LinkedList.Node(3, new LinkedList.Empty())) + ); + PrintList(list); + PrintListWithPropertyMatch(list); + } + + // disable exhaustion check - we know these matches are exhaustive for our purposes, but the compiler doesn't +#pragma warning disable CS8509 + + static void PrintList(LinkedList list) + { + string getPart(LinkedList l) => + l switch + { + LinkedList.Node(var value, var next) => $"(N {value} {getPart(next)})", + LinkedList.Empty => "(E)", + }; + Console.WriteLine(getPart(list)); + } + + // Technically better, but more verbose - property match syntax means that we don't rely on position alone + static void PrintListWithPropertyMatch(LinkedList list) + { + string getPart(LinkedList l) => + l switch + { + LinkedList.Node { Value: var value, Next: var next } => $"(N {value} {getPart(next)})", + LinkedList.Empty => "(E)", + }; + Console.WriteLine(getPart(list)); } } -} \ No newline at end of file +#pragma warning restore CS8509 + + // Linked list with discriminated unions based on records + public abstract record LinkedList + { + public sealed record Node(T Value, LinkedList Next) : LinkedList; + + public sealed record Empty : LinkedList; + } +}