4 ms·
You could make the C# code shorter by using the one-liner record syntax. That would compare the SLOC more fairly.
by ctenb 3y ago
You could make the C# code shorter by using the one-liner record syntax. That would compare the SLOC more fairly.
- piskov 3y agoHere’s version with modern C#: public record Product(string Name, decimal Price); public record OrderLine(Product Product, int Quantity); public abstract record Discount { public record Percentage(decimal Value) : Discount(); public record FixedAmount(decimal Value) : Discount(); } public record Order(List<OrderLine> OrderLines, Discount? Discount) { public decimal CalculateTotalPrice() { var subtotal = OrderLines.Sum(x => x.Product.Price * x.Quantity); return subtotal - Discount switch { Discount.Percentage { } percentage => subtotal * percentage.Value / 100M, Discount.FixedAmount { } amount => amount.Value, _ => 0M }; } }
- CharlieDigital 3y agoI noted the same thing: the C# was unusually verbose. I thought about switching to F# a few months back, but as I started working with it, it wasn't enough of a benefit over C#.
- ctenb 3y agoTo be fair, you'd still need a private constructor in Discount, otherwise the sumtype is not closed, like it is in the F# case. And the percentage Value should be `float` :)
- sparkie 3y agoYou also want the subclasses to be `sealed`. Ideally you would want to write `abstract sealed` for `Discount` too, but C# does not allow it. CIL does support it however, and it is how F# implements sum types. There's no reason I see for C# to continue enforcing this restriction, and lifting it would allow us to write proper DUs.
- ctenb 3y agoWhile I tend to make the SUM type cases sealed, it is theoretically not required to make the sum type closed. All subtypes of a case belong by definition to that case. So any code that handles the defined cases also handles the subclasses implicitly.