Арифметические действия в обобщенных классах - C#
Формулировка задачи:
Здравствуйте! Нужен пример, как ограничить обобщенный тип для написания универсального класса так, чтобы можно было выполнять действия сложения, вычитания, деления и т. п.
P.S. Нужен именно пример кода. На фразы, типа:"Ограничь тип структурой или интерфейсом, а действия реализуй при помощи делегатов" натыкаюсь постоянно, но не совсем понимаю, как это все реализовывается на практике.
Заранее спасибо.
Решение задачи: «Арифметические действия в обобщенных классах»
textual
Листинг программы
- static class MathEx
- {
- }
- static class MathEx<T>
- {
- public static readonly Func<T, T, T> add = BuildBinaryOperator(ExpressionType.Add);
- public static readonly Func<T, T, T> sub = BuildBinaryOperator(ExpressionType.Subtract);
- public static readonly Func<T, T, T> mul = BuildBinaryOperator(ExpressionType.Multiply);
- public static readonly Func<T, T, T> div = BuildBinaryOperator(ExpressionType.Divide);
- static Func<T,T,T> BuildBinaryOperator(ExpressionType Type)
- {
- var t = typeof(T);
- var a = Expression.Parameter(typeof(T), "a");
- var b = Expression.Parameter(typeof(T), "b");
- var o = Expression.MakeBinary(Type, a, b);
- return Expression.Lambda<Func<T, T, T>>(o, a, b).Compile();
- }
- }
- abstract class Vector
- {
- public static Vector<T> Create<T>(params T[] Components)
- => new Vector<T>(Components);
- }
- class Vector<T>: Vector
- {
- T[] data;
- public Vector(int Length)
- {
- data = new T[Length];
- }
- public Vector(IEnumerable<T> Components)
- {
- data = Components.ToArray();
- }
- public int Length => data.Length;
- public T this[int Index]
- {
- get => data[Index];
- set => data[Index] = value;
- }
- public override string ToString()
- {
- return $"<{ string.Join("; ", data) }>";
- }
- private static IEnumerable<R> CheckedZip<R>(Vector<T> Left, Vector<T> Right, Func<T, T, R> ResultSelector)
- {
- if (Left.Length != Right.Length)
- throw new ArgumentException("Vectors must be the same lengths");
- return Left.data.Zip(Right.data, ResultSelector);
- }
- public static Vector<T> operator +(Vector<T> Left, Vector<T> Right)
- => new Vector<T>(CheckedZip(Left, Right, MathEx<T>.add));
- public static Vector<T> operator -(Vector<T> Left, Vector<T> Right)
- => new Vector<T>(CheckedZip(Left, Right, MathEx<T>.sub));
- public static T operator *(Vector<T> Left, Vector<T> Right)
- => CheckedZip(Left, Right, MathEx<T>.mul).Aggregate(MathEx<T>.add);
- public static Vector<T> operator *(Vector<T> Vector, T Scalar)
- => new Vector<T>(Vector.data.Select(Component => MathEx<T>.mul(Component, Scalar)));
- public static Vector<T> operator *(T Scalar, Vector<T> Vector)
- => new Vector<T>(Vector.data.Select(Component => MathEx<T>.mul(Scalar, Component)));
- public static Vector<T> operator /(Vector<T> Vector, T Scalar)
- => new Vector<T>(Vector.data.Select(Component => MathEx<T>.div(Component, Scalar)));
- }
- struct MyValue
- {
- public readonly string Value;
- public MyValue(string Value) => this.Value = Value;
- public override string ToString() => Value;
- public static MyValue operator +(MyValue left, MyValue right) => new MyValue(left.Value + right.Value);
- public static MyValue operator -(MyValue left, MyValue right) => throw new NotImplementedException();
- public static MyValue operator *(MyValue left, MyValue right) => throw new NotImplementedException();
- public static MyValue operator /(MyValue left, MyValue right) => throw new NotImplementedException();
- public static explicit operator MyValue(string Value) => new MyValue(Value);
- }
- class Program
- {
- static void TryAdd<T>(Vector<T> left, Vector<T> right)
- {
- Console.WriteLine($"{typeof(T).Name, 10}: {left} + {right} = {left + right}");
- }
- static void Main()
- {
- var s1 = Vector.Create((MyValue)"a", (MyValue)"b");
- var s2 = Vector.Create((MyValue)"A", (MyValue)"B");
- TryAdd(s1, s2);
- var i1 = Vector.Create(1, 2);
- var i2 = Vector.Create(3, 4);
- TryAdd(i1, i2);
- var f1 = Vector.Create(1.2f, 3.4f);
- var f2 = Vector.Create(5.6f, 7.8f);
- TryAdd(f1, f2);
- var d1 = Vector.Create(1.2d, 3.4d);
- var d2 = Vector.Create(5.6d, 7.8d);
- TryAdd(d1, d2);
- Console.ReadLine();
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д