From d412ebbc304fa186a0b9dffd43ffaf39f37f0b18 Mon Sep 17 00:00:00 2001 From: sharpchen Date: Thu, 28 Dec 2023 01:31:20 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=B0=20update=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...into type manipulation in `typescript`.md} | 0 .../docs/Structural/6. Proxy.md | 61 +++++++++++++++++++ 2 files changed, 61 insertions(+) rename docs/document/Articles/docs/{Pattern matching in type mapping.md => Deep dive into type manipulation in `typescript`.md} (100%) diff --git a/docs/document/Articles/docs/Pattern matching in type mapping.md b/docs/document/Articles/docs/Deep dive into type manipulation in `typescript`.md similarity index 100% rename from docs/document/Articles/docs/Pattern matching in type mapping.md rename to docs/document/Articles/docs/Deep dive into type manipulation in `typescript`.md diff --git a/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md b/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md index 115c636b..ae422665 100644 --- a/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md +++ b/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md @@ -157,6 +157,67 @@ static class NumberExtension ### Percentage Proxy +#### Thing should be implemented + ```cs +var p = 2.Percentage() + 3.Percentage(); // 5% +var p1 = 20 + 30.Percentage(); +var p2 = 2 - 50f.Percentage(); +var p3 = 4 * 25d.Percentage(); +var p4 = 1 / 66m.Percentage(); +var p11 = 30.Percentage() + 20; +var p12 = 2f.Percentage() - 50; +var p13 = 4d.Percentage() * 25; +var p14 = 1m.Percentage() / 66; +``` + +#### Solution + +Solution can be easily achieved using **operator overloading** and **extension methods**. +It's worth noting that, to avoid precision lose of integer types like `int` and `short`, as far as I can tell, there's no way around with `INumber`. So, separated extension methods are needed if you want to implement it for integer types. +```cs +readonly struct Percentage where T : struct, INumber +{ + private readonly T _value; + internal Percentage(T value) => _value = value; + public static T operator +(T left, Percentage right) => left + right._value; + public static T operator -(T left, Percentage right) => left - right._value; + public static T operator *(T left, Percentage right) => left * right._value; + public static T operator /(T left, Percentage right) => left / right._value; + public static Percentage operator +(Percentage left, T right) => new(left._value + right); + public static Percentage operator -(Percentage left, T right) => new(left._value - right); + public static Percentage operator *(Percentage left, T right) => new(left._value * right); + public static Percentage operator /(Percentage left, T right) => new(left._value / right); + public static Percentage operator +(Percentage left, Percentage right) => new(left._value + right._value); + public static Percentage operator -(Percentage left, Percentage right) => new(left._value - right._value); + public static Percentage operator *(Percentage left, Percentage right) => new(left._value * right._value); + public static Percentage operator /(Percentage left, Percentage right) => new(left._value / right._value); + public override string ToString() + { + return _value switch + { + int v => $"{v * 100}%", + float f => $"{f * 100}%", + double d => $"{d * 100}%", + decimal m => $"{m * 100}%", + _ => base.ToString() ?? nameof(Percentage) + }; + } +} +static class PercentageExtension +{ + public static Percentage Percentage(this int number) => new(number / 100m); + public static Percentage Percentage(this T number) + where T : struct, INumber + { + return number switch + { + float f => new(T.CreateChecked(f / 100)), + double d => new(T.CreateChecked(d / 100)), + decimal m => new(T.CreateChecked(m / 100)), + _ => throw new NotImplementedException($"Solution for type: {{{typeof(T).Name}}} is not implemented.") + }; + } +} ```