Question

Je suis en train de comprendre la syntaxe que les supports unboxing un type intégral (court / int / long) à son type intrinsèque, lorsque le type lui-même est inconnue.

Voici un exemple qui illustre complètement arrangé le concept:

 // Just a simple container that returns values as objects
 struct DataStruct
 {
  public short ShortVale;
  public int IntValue;
  public long LongValue;
  public object GetBoxedShortValue() { return ShortVale; }
  public object GetBoxedIntValue() { return IntValue; }
  public object GetBoxedLongValue() { return LongValue; }
 }

 static void Main( string[] args )
 {

  DataStruct data;

  // Initialize data - any value will do
  data.LongValue = data.IntValue = data.ShortVale = 42;

  DataStruct newData;

  // This works if you know the type you are expecting!
  newData.ShortVale = (short)data.GetBoxedShortValue();
  newData.IntValue = (int)data.GetBoxedIntValue();
  newData.LongValue = (long)data.GetBoxedLongValue();

  // But what about when you don't know?
  newData.ShortVale = data.GetBoxedShortValue(); // error
  newData.IntValue = data.GetBoxedIntValue(); // error
  newData.LongValue = data.GetBoxedLongValue(); // error
 }

Dans chaque cas, les types intégrés sont compatibles, donc il devrait y avoir une certaine forme de syntaxe qui dit « l'objet contient un type simple de X, retour que X (même si je ne sais pas ce que X est) » . Parce que les objets viennent finalement de la même source, il ne peut vraiment pas être un décalage (court! = Long).

Je présente mes excuses pour l'exemple artificiel, il semblait que la meilleure façon de démontrer la syntaxe.

Merci.

Était-ce utile?

La solution

Eh bien, le object en lui-même est le type le plus générique le cadre sait. Que ce soit est un type de valeur en boîte (y compris primitive) ou quelque chose d'autre ne le soit; si vous souhaitez obtenir plus vous spécifique Vous pour faire un transtypage à moins que vous restez dans le « faiblement typé » monde avec object (ou, en C # 4, dynamic).

Notez, cependant, que vous pouvez utiliser une liste de conditions pour obtenir ce que vous voulez:

object boxedValue = GetBoxedValue();
if (typeof(short) == boxedValue.GetType()) {
  newData.ShortValue = (short)boxedValue;
} else if (typeof(int) == boxedValue.GetType()) {
  newData.IntValue = (int)boxedValue;
} else if (typeof(long) == boxedValue.GetType()) {
  newData.LongValue = (long)boxedValue;
} else {
  // not one of those
}

Modifier Une "boîte" générique peut également faire ce que vous voulez:

public class Box<T>: IConvertible where T: struct, IConvertible {
    public static implicit operator T(Box<T> boxed) {
        return boxed.Value;
    }

    public static explicit operator Box<T>(T value) {
        return new Box<T>(value);
    }

    private readonly T value;

    public Box(T value) {
        this.value = value;
    }

    public T Value {
        get {
            return value;
        }
    }

    public override bool Equals(object obj) {
        Box<T> boxed = obj as Box<T>;
        if (boxed != null) {
            return value.Equals(boxed.Value);
        }
        return value.Equals(obj);
    }

    public override int GetHashCode() {
        return value.GetHashCode();
    }

    public override string ToString() {
        return value.ToString();
    }

    bool IConvertible.ToBoolean(IFormatProvider provider) {
        return value.ToBoolean(provider);
    }

    char IConvertible.ToChar(IFormatProvider provider) {
        return value.ToChar(provider);
    }

    sbyte IConvertible.ToSByte(IFormatProvider provider) {
        return value.ToSByte(provider);
    }

    byte IConvertible.ToByte(IFormatProvider provider) {
        return value.ToByte(provider);
    }

    short IConvertible.ToInt16(IFormatProvider provider) {
        return value.ToInt16(provider);
    }

    ushort IConvertible.ToUInt16(IFormatProvider provider) {
        return value.ToUInt16(provider);
    }

    int IConvertible.ToInt32(IFormatProvider provider) {
        return value.ToInt32(provider);
    }

    uint IConvertible.ToUInt32(IFormatProvider provider) {
        return value.ToUInt32(provider);
    }

    long IConvertible.ToInt64(IFormatProvider provider) {
        return value.ToInt64(provider);
    }

    ulong IConvertible.ToUInt64(IFormatProvider provider) {
        return value.ToUInt64(provider);
    }

    float IConvertible.ToSingle(IFormatProvider provider) {
        return value.ToSingle(provider);
    }

    double IConvertible.ToDouble(IFormatProvider provider) {
        return value.ToDouble(provider);
    }

    decimal IConvertible.ToDecimal(IFormatProvider provider) {
        return value.ToDecimal(provider);
    }

    DateTime IConvertible.ToDateTime(IFormatProvider provider) {
        return value.ToDateTime(provider);
    }

    string IConvertible.ToString(IFormatProvider provider) {
        return value.ToString(provider);
    }

    object IConvertible.ToType(Type conversionType, IFormatProvider provider) {
        return value.ToType(conversionType, provider);
    }
}

Cela peut ensuite être utilisé au lieu de object; il est encore une référence d'objet, mais il est également fortement typé à la structure d'origine ou d'un type primitif.

Autres conseils

Je ne suis pas tout à fait sûr de ce que vous souhaitez réaliser avec cela, mais votre type de DataStruct est errornous.

Je suppose que, toutes ses méthodes retour LongValue.

struct DataStruct
{
    public short ShortVale;
    public int IntValue;
    public long LongValue;
    public object GetBoxedShortValue() { return ShortVale; }
    public object GetBoxedIntValue() { return IntValue; }
    public object GetBoxedLongValue() { return LongValue; }
}

Sinon, vous pouvez toujours utiliser la classe Convertir pour essayer de convertir entre différents types.
Par exemple:

Convert.ToInt32(SomeObject);

S'il vous plaît préciser votre message (appuyez simplement sur le bouton modifier et de le modifier) ??si vous vouliez dire quelque chose différent.

Par ailleurs, la conversion de object peut être tout à fait sujette à l'erreur car il est le type de base tout. Ainsi, un object peut être quelque chose, et cela signifie que vous ne pouvez pas toujours en toute sécurité convertir un object à un int ou tout autre type.

D'autres exemples:

int value;
try
{
    value = Convert.ToInt32(someObject);
}
catch (FormatException)
{
    // the convertion is unsuccessful
}

Et ceci est également utile:

int myValue;
if (!int.TryParse(something, out myValue))
{
    //unsuccessful
}

J'espère que cette aide.

Vous pouvez revenir dynamic, qui peut ensuite être moulé à un type intégral.

Comme indiqué par d'autres, votre exemple ne fonctionnera pas, parce que vous revenez LongValue de chaque méthode, vous obtiendrez une exception de transtypage invalide ici (une longue boîte ne peut pas être coulé à court).

newData.ShortVale = (short)data.GetBoxedShortValue();

Cependant, l'utilisation de dynamic de C # 4, cela fonctionne (notez les correctifs à vos méthodes GetBoxed et dynamic plutôt que object:

// Just a simple container that returns values as objects
struct DataStruct
{
    public short ShortVale;
    public int IntValue;
    public long LongValue;
    public dynamic GetBoxedShortValue() { return ShortValue; }
    public dynamic GetBoxedIntValue() { return IntValue; }
    public dynamic GetBoxedLongValue() { return LongValue; }
}

static void Main( string[] args )
{
    DataStruct data;

    // Initialize data - any value will do
    data.LongValue = data.IntValue = data.ShortVale = 42;

    DataStruct newData;

    newData.ShortVale = (short)data.GetBoxedShortValue();
    newData.IntValue = (int)data.GetBoxedIntValue();
    newData.LongValue = (long)data.GetBoxedLongValue();

    newData.ShortVale = data.GetBoxedShortValue(); // ok
    newData.IntValue = data.GetBoxedIntValue(); // ok
    newData.LongValue = data.GetBoxedLongValue(); // ok
}

Notez que vous ne avez pas besoin de moulages dans les trois derniers cas. Notez toutefois aussi que si les types ne sont pas alignés, comme dans GetBoxedShortValue() { return LongValue; }, les trois dernières lignes entraîneront des exceptions de la distribution non valides. (Il est intéressant les trois premiers ne seront pas, ils vont simplement travailler, mais quand vous revenez de dynamic en object, ils lancer des exceptions de la distribution non valide.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top