Pregunta

Estoy tratando de encontrar la sintaxis que soporta unboxing un tipo entero (corto / int / largo) a su tipo intrínseco, cuando el tipo en sí es desconocido.

Este es un ejemplo completamente ideado que demuestra el concepto:

 // 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
 }

En cada caso, los tipos integrales son consistentes, por lo que debería haber alguna forma de sintaxis que dice "el objeto contiene un tipo simple de X, retorno que como X (aunque no sé lo que X es)" . Debido a que los objetos en última instancia, provienen de la misma fuente, en realidad no puede haber un desajuste (corto! = Larga).

Me disculpo por el ejemplo artificial, parecía que la mejor manera de demostrar la sintaxis.

Gracias.

¿Fue útil?

Solución

Bueno, el object en sí mismo es el tipo más genérico el marco sabe. Ya sea que es, es un tipo de valor en caja (incluyendo primitivo) o alguna otra cosa no importa; Si desea obtener más específica Tienes para hacer un encasillado si no permanecen en el mundo "en términos generales escrito" con object (o, en C # 4, dynamic).

Tenga en cuenta, sin embargo, que se puede utilizar una lista de condiciones para lograr lo que quiere:

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
}

Editar Una "caja" genérico también puede hacer lo que quiera:

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

Esto puede utilizarse entonces en lugar de object; todavía es una referencia de objeto, sino que también es fuertemente tipado a la estructura original o tipo primitivo.

Otros consejos

No estoy completamente seguro de lo que desea lograr con esto, pero el tipo de DataStruct es errornous.

supongo, no todos sus métodos de devolución 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; }
}

De lo contrario, siempre se puede utilizar la clase Convert para tratar de convertir entre diferentes tipos.
Por ejemplo:

Convert.ToInt32(SomeObject);

Por favor, aclarar su puesto (simplemente pulse el botón de edición y editarlo) si significaba algo diferente.

Por cierto, la conversión de object puede ser bastante propenso a errores, ya que es el tipo de base de todo. Por lo tanto, un object puede ser cualquier cosa, y eso significa que no siempre se puede convertir de forma segura una object a un int o de cualquier otro tipo.

Más ejemplos:

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

Y esto también es útil:

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

Espero que esto ayude.

Puede volver dynamic, que luego se puede convertir a un tipo entero.

Como otros han dicho, su ejemplo no funcionará, debido a que regrese longValue de cada método, de manera que obtendrá una excepción reparto no válido aquí (una caja larga no se puede convertir a corto).

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

Sin embargo, usando C # 4 de dynamic, este trabajo (tenga en cuenta las correcciones a sus métodos y GetBoxed dynamic en lugar de 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
}

Tenga en cuenta que no es necesario ningún moldes en los últimos tres casos. Tenga en cuenta también, sin embargo, que si los tipos no se alinean, como en GetBoxedShortValue() { return LongValue; }, las tres últimas líneas darán lugar a excepciones elenco no válidos. (Es interesante que los tres primeros no lo harán, ellos sólo el trabajo, pero cuando se cambia de vuelta dynamic en object, que será lanzar excepciones elenco no válidos.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top