Skip to content

Commit

Permalink
📰 update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpchen committed Dec 27, 2023
1 parent 036b547 commit d412ebb
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
61 changes: 61 additions & 0 deletions docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>`. So, separated extension methods are needed if you want to implement it for integer types.

```cs
readonly struct Percentage<T> where T : struct, INumber<T>
{
private readonly T _value;
internal Percentage(T value) => _value = value;
public static T operator +(T left, Percentage<T> right) => left + right._value;
public static T operator -(T left, Percentage<T> right) => left - right._value;
public static T operator *(T left, Percentage<T> right) => left * right._value;
public static T operator /(T left, Percentage<T> right) => left / right._value;
public static Percentage<T> operator +(Percentage<T> left, T right) => new(left._value + right);
public static Percentage<T> operator -(Percentage<T> left, T right) => new(left._value - right);
public static Percentage<T> operator *(Percentage<T> left, T right) => new(left._value * right);
public static Percentage<T> operator /(Percentage<T> left, T right) => new(left._value / right);
public static Percentage<T> operator +(Percentage<T> left, Percentage<T> right) => new(left._value + right._value);
public static Percentage<T> operator -(Percentage<T> left, Percentage<T> right) => new(left._value - right._value);
public static Percentage<T> operator *(Percentage<T> left, Percentage<T> right) => new(left._value * right._value);
public static Percentage<T> operator /(Percentage<T> left, Percentage<T> 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<T>)
};
}
}
static class PercentageExtension
{
public static Percentage<decimal> Percentage(this int number) => new(number / 100m);
public static Percentage<T> Percentage<T>(this T number)
where T : struct, INumber<T>
{
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.")
};
}
}
```

0 comments on commit d412ebb

Please sign in to comment.