Арифметические действия в обобщенных классах - 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(); } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д