0

我正在编写一个自定义的通用 VectorN 类,其中 T:struct、IFormattable、IComparable、IConvertible。我可以通过 this[int index] 访问向量的索引值。所以在一个循环中,我执行这段代码来制作 VectorN.One:

r[i] = (T)Convert.ChangeType(1, typeof(T));

它与标准数字(例如 int、decimal 等)完美配合,但是当我编写自定义 struct uHalfByte 进行测试时,它给出了错误:

从“System.Int32”到“uHalfByte”的无效转换。

这是uHalfByte的脚本:

struct uHalfByte : IFormattable, IComparable<uHalfByte>, IConvertible
{
    private byte val;
    public byte Val
    {
        get { return (byte)(val & 0xF); }
        set { val = (byte)(value & 0xF); }
    }
    public uHalfByte(byte val)
    {
        this.val = (byte)(val & 0xF);
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        if (formatProvider == null) formatProvider = System.Globalization.CultureInfo.CurrentCulture;
        if (string.IsNullOrEmpty(format)) format = "G";
        string s = "";
        for (int i = 0; i < 4; i++) s += ((Val >> i) & 1).ToString(format,formatProvider);
        return s;
    }

    public int CompareTo(uHalfByte other)
    {
        return this.Val - other.Val;
    }

    public TypeCode GetTypeCode()
    {
        return TypeCode.Byte;
    }

    public bool ToBoolean(IFormatProvider provider)
    {
        return val!=0;
    }

    public char ToChar(IFormatProvider provider)
    {
        return (char)val;
    }

    public sbyte ToSByte(IFormatProvider provider)
    {
        return (sbyte)val;
    }

    public byte ToByte(IFormatProvider provider)
    {
        return (byte)val;
    }

    public short ToInt16(IFormatProvider provider)
    {
        return (short)val;
    }

    public ushort ToUInt16(IFormatProvider provider)
    {
        return (ushort)val;
    }

    public int ToInt32(IFormatProvider provider)
    {
        return (int)val;
    }

    public uint ToUInt32(IFormatProvider provider)
    {
        return (uint)val;
    }

    public long ToInt64(IFormatProvider provider)
    {
        return (long)val;
    }

    public ulong ToUInt64(IFormatProvider provider)
    {
        return (ulong)val;
    }

    public float ToSingle(IFormatProvider provider)
    {
        return (float)val;
    }

    public double ToDouble(IFormatProvider provider)
    {
        return (double)val;
    }

    public decimal ToDecimal(IFormatProvider provider)
    {
        return (decimal)val;
    }

    public DateTime ToDateTime(IFormatProvider provider)
    {
        return new DateTime(val);
    }

    public string ToString(IFormatProvider provider)
    {
        return ToString("", provider);
    }

    public object ToType(Type conversionType, IFormatProvider provider)
    {
        return Convert.ChangeType(val, conversionType);
    }

    public static explicit operator uHalfByte(int val)
    {
        return new uHalfByte((byte)val);
    }
}

我在 uHalfByte 中做错了什么还是不可能?

4

2 回答 2

1

它不会以这种方式工作,因为System.Int32(如异常消息中所述)没有关于您的自定义类uHalfByte的信息并且无法执行该转换。当然它会以其他方式工作uHalfByte -> int

编辑:
在您的情况下,我认为您可以使用转换运算符: https ://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/using-conversion-operators

像这样:

struct uHalfByte
{
    public static explicit operator uHalfByte(int value)
    {
        return new uHalfByte();
    }
    public static explicit operator uHalfByte(string value)
    {
        return new uHalfByte();
    }
}

用法:

if (typeof(T) == typeof(uHalfByte)) 
    r[i] = (uHalfByte)value;
else
    r[i] = (T)Convert.ChangeType(value, typeof(T));
于 2017-10-17T13:20:18.860 回答
0

基于@Thowk 的答案的解决方案:实现了一个通用接口:

public interface INumber<T>
{
    T ConvertGeneric<T1>(T1 item);
}

在我的脚本中添加了接口的实现:

    public struct uHalfByte : IFormattable, IComparable<uHalfByte>, IConvertible, INumber<uHalfByte>
    {
        ...
        public uHalfByte ConvertGeneric<T>(T item)
        {
            if (typeof(T) == typeof(int))
            {
                return new uHalfByte((byte)(int)Convert.ChangeType(item, typeof(int)));
            }
            else if (typeof(T) == typeof(uint))
            {
                return new uHalfByte((byte)(uint)Convert.ChangeType(item, typeof(uint)));
            }
            else if (typeof(T) == typeof(long))
            {
                return new uHalfByte((byte)(long)Convert.ChangeType(item, typeof(long)));
            }
            else if (typeof(T) == typeof(ulong))
            {
                return new uHalfByte((byte)(ulong)Convert.ChangeType(item, typeof(ulong)));
            }
            else if (typeof(T) == typeof(short))
            {
                return new uHalfByte((byte)(short)Convert.ChangeType(item, typeof(short)));
            }
            else if (typeof(T) == typeof(ushort))
            {
                return new uHalfByte((byte)(ushort)Convert.ChangeType(item, typeof(ushort)));
            }
            else if (typeof(T) == typeof(byte))
            {
                return new uHalfByte((byte)Convert.ChangeType(item, typeof(byte)));
            }
            else if (typeof(T) == typeof(sbyte))
            {
                return new uHalfByte((byte)(sbyte)Convert.ChangeType(item, typeof(sbyte)));
            }
            else throw new NotSupportedException(string.Format("Type {0} is not supported, you have to write your own function!", typeof(T)));
        }
    }
于 2017-10-18T10:43:37.343 回答