2017-10-17 5 views
0

J'écris une classe VectorN générique personnalisée, où T: struct, IFormattable, IComparable, IConvertible. Je peux accéder à une valeur indexée de vecteur par cet [index int]. Donc, dans une boucle que je fais ce morceau de code pour faire VectorN.One:Transmettre de la structure int personnalisée à la structure C#

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

Il fonctionne parfaitement avec des nombres standards tels que int, décimal, etc., mais quand je l'ai écrit un uHalfByte struct personnalisé pour les tests, il donne une erreur:

Invalid cast from 'System.Int32' to 'uHalfByte'.

Voici le script de 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); 
    } 
} 

Ai-je fait quelque chose de mal dans uHalfByte ou il est tout simplement impossible?

Répondre

0

Il ne fonctionne pas de cette façon, parce que System.Int32 (comme indiqué dans le message d'exception) ont aucune information sur votre classe personnalisée uHalfByte et ne peut pas effectuer cette conversion. Bien sûr, il va le travailler autrement uHalfByte -> int

Edit:
Dans votre cas, je pense que vous pouvez utiliser des opérateurs de conversion: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/using-conversion-operators

comme ceci:

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

utilisation:

if (typeof(T) == typeof(uHalfByte)) 
    r[i] = (uHalfByte)value; 
else 
    r[i] = (T)Convert.ChangeType(value, typeof(T)); 
+0

Cependant, il n'y a pas de possibilité de mettre en œuvre un constructeur dans une interface struct et aucune option pour utiliser une classe abstraite comme base de struct. Comment devrait ressembler IMyConvertibleExample? – mcmikecreations

0

La solution basée sur la réponse de @Thowk: Mis en œuvre une interface générique:

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

Ajout d'une implémentation de l'interface dans mon script:

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))); 
     } 
    }