Реализация типа-обёртки

127
16 марта 2022, 07:00

Помогите исправить код. Я пишу тип-обёртку в проекте для нейронных сетей и я хочу чтобы изменяя в этой структуре тип с double на float, ufloat, double, udouble, ulong или другой числовой, все функции приведения типов, конструкторы, неявные преобразования работали корректно. Пожалуйста, посмотрите и исправьте в коде некорректные реализации:

using System;
namespace Neuronet
{
    /// <summary>
    /// Тип параметров нейрона
    /// </summary>
    public struct NType : IComparable, IComparable<NType>, IConvertible, IEquatable<NType>, IFormattable
    {
        /// <summary>
        /// Значение, выражающее тип параметров нейрона
        /// Сейчас double, вы можете сменить тип, изменяя тип value, MinValue, MaxValue, Epsilon 
        /// </summary>
        readonly double value;
        public const double MinValue = double.MinValue;
        public const double MaxValue = double.MaxValue;
        public const double Epsilon = double.Epsilon;
        #region ctors
        /// <summary>
        /// Конструктор от int
        /// </summary>
        /// <param name="val">Значение</param>
        public NType(int v)
        {
            value = v;
        }
        public NType(double v)
        {
            value = v;
        }
        public NType(float v)
        {
            value = v;
        }
        public NType(uint v)
        {
            value = v;
        }
        public NType(Int16 v)
        {
            value = v;
        }
        public NType(UInt16 v)
        {
            value = v;
        }
        public NType(Int64 v)
        {
            value = v;
        }
        public NType(UInt64 v)
        {
            value = v;
        }
        public NType(NType v)
        {
            value = v;
        }
        #endregion
        #region comparse
        public override bool Equals(object obj)
            => obj is NType check && Equals(check);
        public override int GetHashCode()
        {
            return value.GetHashCode();
        }
        public bool Equals(NType other)
        {
            return this.value == other.value;
        }
        public int CompareTo(object obj)
        {
            if (obj is NType other)
                return CompareTo(other);
            else
                return -1; /// Неприводимые объекты больше приводимых
        }
        #endregion
        #region converts
        public static NType ToNType(int v)
        {
            return new NType(v);
        }
        public string ToString(string format, IFormatProvider formatProvider)
        {
            return value.ToString(format, formatProvider);
        }
        public TypeCode GetTypeCode()
        {
            return value.GetTypeCode();
        }
        public bool ToBoolean(IFormatProvider provider)
        {
            return value == 0 ? false : true;
        }
        public char ToChar(IFormatProvider provider)
        {
            return (char)value;
        }
        public sbyte ToSByte(IFormatProvider provider)
        {
            return (sbyte)value;
        }
        public byte ToByte(IFormatProvider provider)
        {
            return (byte)value;
        }
        public short ToInt16(IFormatProvider provider)
        {
            return (Int16)value;
        }
        public ushort ToUInt16(IFormatProvider provider)
        {
            return (UInt16)value;
        }
        public int ToInt32(IFormatProvider provider)
        {
            return (Int32)value;
        }
        public uint ToUInt32(IFormatProvider provider)
        {
            return (UInt32)value;
        }
        public long ToInt64(IFormatProvider provider)
        {
            return (Int64)value;
        }
        public ulong ToUInt64(IFormatProvider provider)
        {
            return (UInt64)value;
        }
        public float ToSingle(IFormatProvider provider)
        {
            return (float)value;
        }
        public double ToDouble(IFormatProvider provider)
        {
            return (double)value;
        }
        public decimal ToDecimal(IFormatProvider provider)
        {
            return (decimal)value;
        }
        public DateTime ToDateTime(IFormatProvider provider)
        {
            return new DateTime((long)value);
        }
        public string ToString(IFormatProvider provider)
        {
            return value.ToString(provider);
        }
        public object ToType(Type conversionType, IFormatProvider provider)
        {
            return ((IConvertible)value).ToType(conversionType, provider);
        }
        public int CompareTo(NType other)
              => value.CompareTo(other.value);
        #endregion
        #region overloads
        public static bool operator ==(NType left, NType right)
        {
            return left.Equals(right);
        }
        public static bool operator !=(NType left, NType right)
        {
            return !(left == right);
        }
        public static bool operator <(NType left, NType right)
        {
            return left.CompareTo(right) < 0;
        }
        public static bool operator <=(NType left, NType right)
        {
            return left.CompareTo(right) <= 0;
        }
        public static bool operator >(NType left, NType right)
        {
            return left.CompareTo(right) > 0;
        }
        public static bool operator >=(NType left, NType right)
        {
            return left.CompareTo(right) >= 0;
        }
        public static NType operator +(NType left, NType right)
        {
            return new NType(left.value + right.value);
        }
        public static NType Add(NType left, NType right)
        {
            return left + right;
        }
        public static NType operator -(NType left, NType right)
        {
            return new NType(left.value - right.value);
        }
        public static NType Subtract(NType left, NType right)
        {
            return left - right;
        }
        public static NType operator *(NType left, NType right)
        {
            return new NType(left.value * right.value);
        }
        public static NType Multiply(NType left, NType right)
        {
            return left * right;
        }
        public static NType operator /(NType left, NType right)
        {
            return new NType(left.value / right.value);
        }
        public static NType Divide(NType left, NType right)
        {
            return left / right;
        }
        public static NType operator %(NType left, NType right)
        {
            return new NType(left.value % right.value);
        }
        public static NType Mod(NType left, NType right)
        {
            return left % right;
        }
        public static NType Increment(NType item)
        {
            var val = item.value;
            return new NType(val++);
        }
        public static NType Decrement(NType item)
        {
            var val = item.value;
            return new NType(val--);
        }
        #endregion
        #region implicits
        ///// <summary>
        ///// Неявное приведение типа от int к NType
        ///// </summary>
        ///// <param name="v">Значение</param>
        public static implicit operator NType(int v)
        {
            return new NType(v);
        }
        public static implicit operator NType(double v)
        {
            return new NType(v);
        }
        public static implicit operator NType(float v)
        {
            return new NType(v);
        }
        public static implicit operator NType(uint v)
        {
            return new NType(v);
        }
        public static implicit operator NType(Int16 v)
        {
            return new NType(v);
        }
        public static implicit operator NType(UInt16 v)
        {
            return new NType(v);
        }
        public static implicit operator NType(Int64 v)
        {
            return new NType(v);
        }
        public static implicit operator NType(UInt64 v)
        {
            return new NType(v);
        }
        public static implicit operator double(NType v)
        {
            return (double)v.value;
        }
        public static implicit operator float(NType v)
        {
            return (float)v.value;
        }
        public static implicit operator int(NType v)
        {
            return (int)v.value;
        }
        public static implicit operator uint(NType v)
        {
            return (uint)v.value;
        }
        public static implicit operator Int16(NType v)
        {
            return (Int16)v.value;
        }
        public static implicit operator UInt16(NType v)
        {
            return (UInt16)v.value;
        }
        public static implicit operator Int64(NType v)
        {
            return (Int64)v.value;
        }
        public static implicit operator UInt64(NType v)
        {
            return (UInt64)v.value;
        }
        #endregion
    }
}
Answer 1

В общем, я так реализовал:

using System;
namespace Neuronet
{
    /// <summary>
    /// Тип параметров нейрона
    /// </summary>
    public struct NType : IComparable, IComparable<NType>, IConvertible, IEquatable<NType>, IFormattable
    {
        /// <summary>
        /// Значение, выражающее тип параметров нейрона
        /// Сейчас double, вы можете сменить тип, изменяя тип value,
        /// MinValue, MaxValue, Epsilon и изменив конструктор.
        /// </summary>
        readonly double value;
        public const double MinValue = double.MinValue;
        public const double MaxValue = double.MaxValue;
        public const double Epsilon = double.Epsilon;
        #region ctors
        /// <summary>
        /// Конструктор от object
        /// </summary>
        /// <param name="v">Значение</param>
        public NType(object v)
        {
            if (v == null) { throw new ArgumentException(Resources.Error_2); }
            value = Convert.ToDouble(v, System.Globalization.CultureInfo.InvariantCulture);
        }
        #endregion
        #region comparse
        public override bool Equals(object obj)
            => obj is NType check && Equals(check);
        public override int GetHashCode()
        {
            return value.GetHashCode();
        }
        public bool Equals(NType other)
        {
            return this.value == other.value;
        }
        public int CompareTo(object obj)
        {
            if (obj is NType other)
                return CompareTo(other);
            else
                return -1; /// Неприводимые объекты больше приводимых
        }
        #endregion
        #region converts
        public static NType ToNType(int v)
        {
            return new NType(v);
        }
        public string ToString(string format, IFormatProvider formatProvider)
        {
            return value.ToString(format, formatProvider);
        }
        public TypeCode GetTypeCode()
        {
            return value.GetTypeCode();
        }
        public bool ToBoolean(IFormatProvider provider)
        {
            return Convert.ToBoolean(value, provider);
        }
        public char ToChar(IFormatProvider provider)
        {
            return Convert.ToChar(value, provider);
        }
        public sbyte ToSByte(IFormatProvider provider)
        {
            return Convert.ToSByte(value, provider);
        }
        public byte ToByte(IFormatProvider provider)
        {
            return Convert.ToByte(value, provider);
        }
        public short ToInt16(IFormatProvider provider)
        {
            return Convert.ToInt16(value, provider);
        }
        public ushort ToUInt16(IFormatProvider provider)
        {
            return Convert.ToUInt16(value, provider);
        }
        public int ToInt32(IFormatProvider provider)
        {
            return Convert.ToInt32(value, provider);
        }
        public uint ToUInt32(IFormatProvider provider)
        {
            return Convert.ToUInt32(value, provider);
        }
        public long ToInt64(IFormatProvider provider)
        {
            return Convert.ToInt64(value, provider);
        }
        public ulong ToUInt64(IFormatProvider provider)
        {
            return Convert.ToUInt64(value, provider);
        }
        public float ToSingle(IFormatProvider provider)
        {
            return Convert.ToSingle(value, provider);
        }
        public double ToDouble(IFormatProvider provider)
        {
            return Convert.ToDouble(value, provider);
        }
        public decimal ToDecimal(IFormatProvider provider)
        {
            return Convert.ToDecimal(value, provider);
        }
        public DateTime ToDateTime(IFormatProvider provider)
        {
            return Convert.ToDateTime(value, provider);
        }
        public string ToString(IFormatProvider provider)
        {
            return Convert.ToString(value, provider);
        }
        public object ToType(Type conversionType, IFormatProvider provider)
        {
            return Convert.ChangeType(value, conversionType, provider);
        }
        public int CompareTo(NType other)
              => value.CompareTo(other.value);
        #endregion
        #region overloads
        public static bool operator ==(NType left, NType right)
        {
            return left.Equals(right);
        }
        public static bool operator !=(NType left, NType right)
        {
            return !(left == right);
        }
        public static bool operator <(NType left, NType right)
        {
            return left.CompareTo(right) < 0;
        }
        public static bool operator <=(NType left, NType right)
        {
            return left.CompareTo(right) <= 0;
        }
        public static bool operator >(NType left, NType right)
        {
            return left.CompareTo(right) > 0;
        }
        public static bool operator >=(NType left, NType right)
        {
            return left.CompareTo(right) >= 0;
        }
        public static NType operator +(NType left, NType right)
        {
            return new NType(left.value + right.value);
        }
        public static NType Add(NType left, NType right)
        {
            return left + right;
        }
        public static NType operator -(NType left, NType right)
        {
            return new NType(left.value - right.value);
        }
        public static NType Subtract(NType left, NType right)
        {
            return left - right;
        }
        public static NType operator *(NType left, NType right)
        {
            return new NType(left.value * right.value);
        }
        public static NType Multiply(NType left, NType right)
        {
            return left * right;
        }
        public static NType operator /(NType left, NType right)
        {
            return new NType(left.value / right.value);
        }
        public static NType Divide(NType left, NType right)
        {
            return left / right;
        }
        public static NType operator %(NType left, NType right)
        {
            return new NType(left.value % right.value);
        }
        public static NType Mod(NType left, NType right)
        {
            return left % right;
        }
        public static NType Increment(NType item)
        {
            var val = item.value;
            return new NType(val++);
        }
        public static NType Decrement(NType item)
        {
            var val = item.value;
            return new NType(val--);
        }
        #endregion
        #region implicits
        ///// <summary>
        ///// Неявное приведение типа от int к NType
        ///// </summary>
        ///// <param name="v">Значение</param>
        public static implicit operator NType(int v)
        {
            return new NType(v);
        }
        public static implicit operator NType(double v)
        {
            return new NType(v);
        }
        public static implicit operator NType(float v)
        {
            return new NType(v);
        }
        public static implicit operator NType(uint v)
        {
            return new NType(v);
        }
        public static implicit operator NType(Int16 v)
        {
            return new NType(v);
        }
        public static implicit operator NType(UInt16 v)
        {
            return new NType(v);
        }
        public static implicit operator NType(Int64 v)
        {
            return new NType(v);
        }
        public static implicit operator NType(UInt64 v)
        {
            return new NType(v);
        }
        public static implicit operator double(NType v)
        {
            return (double)v.value;
        }
        public static implicit operator float(NType v)
        {
            return (float)v.value;
        }
        public static implicit operator int(NType v)
        {
            return (int)v.value;
        }
        public static implicit operator uint(NType v)
        {
            return (uint)v.value;
        }
        public static implicit operator Int16(NType v)
        {
            return (Int16)v.value;
        }
        public static implicit operator UInt16(NType v)
        {
            return (UInt16)v.value;
        }
        public static implicit operator Int64(NType v)
        {
            return (Int64)v.value;
        }
        public static implicit operator UInt64(NType v)
        {
            return (UInt64)v.value;
        }
        #endregion
    }
}
READ ALSO
Перенести отдельный коммит из другой ветки visual studio

Перенести отдельный коммит из другой ветки visual studio

Я могу переместить все изменения, используя функцию Visual Studio Переместить изменения из одной ветви в другую

74
Скрытые объекты на сцене

Скрытые объекты на сцене

Допустим, имеется 10 скрытых объектов на сцене

81
Как проскролить DataGrid который в ScrollView?

Как проскролить DataGrid который в ScrollView?

Мне кажется это достаточно общая ситуация, но я не могу найти правильное решение

141
Не получается запустить с помощью события, строку в методе void

Не получается запустить с помощью события, строку в методе void

возникла ситуация, именно через void не получается запустить программу, а вернее не понимаю, как это сделать

89