add property match for records
This commit is contained in:
+69
-14
@@ -1,34 +1,39 @@
|
|||||||
// ReSharper disable All
|
// ReSharper disable All
|
||||||
|
|
||||||
namespace CS9 {
|
namespace CS9
|
||||||
class Program {
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
// Relational patterns (>= operator et al.)
|
// Relational patterns (>= operator et al.)
|
||||||
|
|
||||||
// Logical patterns ("or", also "and" and "not")
|
// Logical patterns ("or", also "and" and "not")
|
||||||
// Note: parens ( and ) can be used to determine precedence
|
// Note: parens ( and ) can be used to determine precedence
|
||||||
bool IsPastMidYear(DateTime dt) => dt is { Month: >= 7 };
|
bool IsPastMidYear(DateTime dt) => dt is { Month: >= 7 };
|
||||||
|
|
||||||
bool IsThisYearOrLast(DateTime dt) => dt is { Year: 2022 or 2021 };
|
bool IsThisYearOrLast(DateTime dt) => dt is { Year: 2022 or 2021 };
|
||||||
|
|
||||||
bool IsSummer(DateTime dt) => dt is
|
bool IsSummer(DateTime dt) =>
|
||||||
{ Month: 7 or 8 } or
|
dt is { Month: 7 or 8 } or { Month: 6, Day: >= 21 } or { Month: 9, Day: < 21 };
|
||||||
{ Month: 6, Day: >= 21 } or
|
|
||||||
{ Month: 9, Day: < 21 };
|
|
||||||
|
|
||||||
// Class with "Deconstruct" implementation
|
// Class with "Deconstruct" implementation
|
||||||
class Order {
|
class Order
|
||||||
|
{
|
||||||
public int ItemCount { get; set; }
|
public int ItemCount { get; set; }
|
||||||
public double ItemPrice { 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;
|
itemCount = ItemCount;
|
||||||
itemPrice = ItemPrice;
|
itemPrice = ItemPrice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum OrderValue {
|
public enum OrderValue
|
||||||
|
{
|
||||||
ValuableDueToHighCount,
|
ValuableDueToHighCount,
|
||||||
ValuableDueToHighItemPrice,
|
ValuableDueToHighItemPrice,
|
||||||
ValuableDueToHighTotal,
|
ValuableDueToHighTotal,
|
||||||
NotValuable
|
NotValuable,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Positional patterns with "discard" placeholders - note that
|
// Positional patterns with "discard" placeholders - note that
|
||||||
@@ -38,7 +43,9 @@ namespace CS9 {
|
|||||||
{
|
{
|
||||||
// Labels are optional here but can be useful
|
// Labels are optional here but can be useful
|
||||||
// for readability
|
// 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!"),
|
(_, < 0) => throw new ArgumentException("Positive itemPrices please!"),
|
||||||
(>= 100, _) => OrderValue.ValuableDueToHighCount,
|
(>= 100, _) => OrderValue.ValuableDueToHighCount,
|
||||||
(_, >= 1000) => OrderValue.ValuableDueToHighItemPrice,
|
(_, >= 1000) => OrderValue.ValuableDueToHighItemPrice,
|
||||||
@@ -46,10 +53,58 @@ namespace CS9 {
|
|||||||
// Assign variable names for further processing
|
// Assign variable names for further processing
|
||||||
var (c, p) when c * p > 1000 => OrderValue.ValuableDueToHighTotal,
|
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<int> list = new LinkedList<int>.Node(
|
||||||
|
1,
|
||||||
|
new LinkedList<int>.Node(2, new LinkedList<int>.Node(3, new LinkedList<int>.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<T>(LinkedList<T> list)
|
||||||
|
{
|
||||||
|
string getPart(LinkedList<T> l) =>
|
||||||
|
l switch
|
||||||
|
{
|
||||||
|
LinkedList<T>.Node(var value, var next) => $"(N {value} {getPart(next)})",
|
||||||
|
LinkedList<T>.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<T>(LinkedList<T> list)
|
||||||
|
{
|
||||||
|
string getPart(LinkedList<T> l) =>
|
||||||
|
l switch
|
||||||
|
{
|
||||||
|
LinkedList<T>.Node { Value: var value, Next: var next } => $"(N {value} {getPart(next)})",
|
||||||
|
LinkedList<T>.Empty => "(E)",
|
||||||
|
};
|
||||||
|
Console.WriteLine(getPart(list));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
#pragma warning restore CS8509
|
||||||
|
|
||||||
|
// Linked list with discriminated unions based on records
|
||||||
|
public abstract record LinkedList<T>
|
||||||
|
{
|
||||||
|
public sealed record Node(T Value, LinkedList<T> Next) : LinkedList<T>;
|
||||||
|
|
||||||
|
public sealed record Empty : LinkedList<T>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user