Вопрос

Я пытаюсь понять синтаксис, который поддерживает Unboxing Integral Type (Collect / int / long) к его внутреннему типу, когда сам тип неизвестен.

Вот полностью надуманный пример, который демонстрирует концепцию:

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

В каждом случае интегральные типы являются последовательными, поэтому должна быть некоторая форма синтаксиса, которая гласит, что «Объект содержит простой тип X, возврат, что как X (даже если я не знаю, что х)». Поскольку объекты в конечном итоге приходят из того же источника, на самом деле не может быть несоответствием (коротко! = Долго).

Я прошу прощения за надуманный пример, казалось, что лучший способ продемонстрировать синтаксис.

Спасибо.

Это было полезно?

Решение

Ну, то object Сам по себе является самым универсальным типом в рамках. Будь то тип коробки (включая примитив) или что-то еще не имеет значения; Если вы хотите получить более конкретно, вы имеют сделать попечку, если вы не останетесь в «слабо набранном» мире object (или, в C # 4, dynamic).

Обратите внимание, однако, что вы можете использовать список условий для достижения того, что вы хотите:

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
}

Редактировать: Общая «коробка» может также сделать то, что вы хотите:

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

Затем можно использовать вместо object; Это все еще ссылка на объект, но она также сильно набирается в исходной структуре или примитивном типе.

Другие советы

Я не совсем уверен в том, что вы хотели бы достичь с этим, но ваш тип Datastruct Airornous.

Я полагаю, не все его методы возвращают 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; }
}

В противном случае вы всегда можете использовать класс Convert, чтобы попытаться преобразовать между различными типами.
Например:

Convert.ToInt32(SomeObject);

Пожалуйста, уточните ваш пост (просто нажмите кнопку редактирования и отредактировать его), если вы имели в виду что-то другое.

Кстати, преобразование из object Может быть довольно подверженным ошибкам, так как это базовый тип всего. Итак, Ан object может быть что угодно, и это означает, что вы не всегда можете безопасно преобразовать object к INT или любому другому типу.

Больше примеров:

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

И это также полезно:

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

Надеюсь, это поможет.

Вы можете вернуть dynamic, который затем может быть отброшен в интегральный тип.

Как указано другими, ваш пример не будет работать, потому что вы возвращаете LongValue из каждого метода, поэтому вы получите неверное исключение отличия здесь (коробка длина не может быть сброшена).

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

Однако, используя C # 4 dynamic, это будет работать (обратите внимание на исправления к вашим методам GetBoxed и dynamic скорее, чем 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
}

Обратите внимание, что вам не нужны кавычки в последние три случая. Обратите внимание, однако, что если типы не выровняются, как в GetBoxedShortValue() { return LongValue; }, Последние три строки приведут к недействительным исключениям литых. (Интересно, что первые три не будут, они просто будут работать, но когда вы меняете dynamic Вернуться в object, Oни бросит недействительные исключения.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top