Лучший способ привести объект к int

179

Это, вероятно, тривиально, но я не могу придумать лучшего способа сделать это. У меня есть COM-объект, который возвращает вариант, который становится объектом в C #. Единственный способ, которым я могу получить это в Int

int test = int.Parse(string.Format("{0}", myobject))

Есть ли более чистый способ сделать это? Спасибо

Стив
источник

Ответы:

362

У вас есть несколько вариантов:

  • (int)- Оператор броска. Работает, если объект уже является целым на некотором уровне в иерархии наследования или если определено неявное преобразование.

  • int.Parse()/int.TryParse() - Для преобразования из строки неизвестного формата.

  • int.ParseExact()/int.TryParseExact() - Для преобразования из строки в определенном формате

  • Convert.ToInt32() - Для преобразования объекта неизвестного типа. Он будет использовать явное и неявное преобразование или реализацию IConvertible, если таковые определены.

  • as int?- Обратите внимание "?". asОператор только для ссылочных типов, и поэтому я использовал «?» чтобы обозначить Nullable<int>. Оператор " as" работает, как Convert.To____(), но думать, TryParse()а не Parse(): он возвращает, nullа не выдает исключение, если преобразование не удается.

Из них я бы предпочел, (int)чтобы объект на самом деле представлял собой целое в штучной упаковке. В противном случае используйте Convert.ToInt32()в этом случае.

Обратите внимание, что это очень общий ответ: я хочу обратить внимание на ответ Даррена Кларка, потому что я думаю, что он хорошо справляется со спецификой , но пришел поздно и еще не проголосовал. Во всяком случае, он получает мой голос за «принятый ответ», за рекомендацию (int), за указание на то, что в случае неудачи он (int)(short)может работать, и за рекомендацию проверить ваш отладчик, чтобы узнать фактический тип времени выполнения.

Джоэл Коухорн
источник
Я нашел точку, которая на самом деле не была ошибкой, но, возможно, слишком сильно упростила вещи, чтобы кто-то мог подумать об этом. Я удалил это предложение и добавил ссылку на достоверную документацию.
Джоэл Коухорн
Будет ли прямой акт работать с неявным преобразованием? У меня сложилось впечатление, что это будет делать только распаковку, а не любые другие преобразования.
Даррен Кларк
Не совсем ответ, но прочитайте это: blogs.msdn.com/ericlippert/archive/2009/03/19/…
Джоэл Кохорн
В результате он определенно делает больше, чем просто распаковывает. В противном случае, почему вы могли бы использовать его, например, для приведения двойного к int?
Джоэл Коухорн
И, читая некоторые другие вещи, я могу иметь неявное / явное задом наперед, но в любом случае, я думаю, это поможет понять смысл.
Джоэл Коухорн
41

Актерский состав (int) myobject должен просто работать.

Если это дает вам недопустимое исключение приведения, то это, вероятно, потому, что тип варианта не VT_I4. Бьюсь об заклад, что вариант с VT_I4 конвертируется в упакованный int, VT_I2 в упакованный короткий и т. Д.

При приведении типа в штучной упаковке допустимо только приведение к типу в штучной упаковке. Например, если возвращаемый вариант - VT_I2, он (int) (short) myObjectдолжен работать.

Самый простой способ выяснить это - проверить возвращаемый объект и взглянуть на его тип в отладчике. Также убедитесь, что в сборке взаимодействия у вас есть возвращаемое значение, помеченное какMarshalAs(UnmanagedType.Struct)

Даррен Кларк
источник
32

Convert.ToInt32 (MyObject);

это будет обрабатывать случай, когда myobject имеет значение null и возвращает 0, вместо того, чтобы выдавать исключение.

Захир Дж
источник
Я получаю «Не удается разрешить символ« ToInt »», когда я пытаюсь сделать это следующим образом. Это работает только если я использую, например ToInt32.
Тобиас Фейл
Где мы можем найти этот метод? Это в .Net Framework Library?
Амир Пурманд امیر پورمند
8

Используйте Int32.TryParseследующим образом.

  int test;
  bool result = Int32.TryParse(value, out test);
  if (result)
  {
     Console.WriteLine("Sucess");         
  }
  else
  {
     if (value == null) value = ""; 
     Console.WriteLine("Failure");
  }
Срикар Додди
источник
Фактически, Parse вызывает TryParse и выдает исключение, если TryParse возвращает false. Так что TryParse не обрабатывает исключение, потому что оно никогда не выбрасывает.
Самуил
Технически, они оба вызывают один и тот же метод NumberToInt32, но только Parse генерирует исключения, когда он не работает.
Самуил
TryParse по-прежнему требует преобразования варианта в строку. AFAIK проблема не в преобразовании строки в тип int, а в вариант, представляющий тип int, в фактический тип int.
Даррен Кларк
3

Я перечисляю разницу в каждом из способов кастинга. Что за конкретный тип литья ручки и нет?

    // object to int
    // does not handle null
    // does not handle NAN ("102art54")
    // convert value to integar
    int intObj = (int)obj;

    // handles only null or number
    int? nullableIntObj = (int?)obj; // null
    Nullable<int> nullableIntObj1 = (Nullable<int>)obj; // null

   // best way for casting from object to nullable int
   // handles null 
   // handles other datatypes gives null("sadfsdf") // result null
    int? nullableIntObj2 = obj as int?; 

    // string to int 
    // does not handle null( throws exception)
    // does not string NAN ("102art54") (throws exception)
    // converts string to int ("26236")
    // accepts string value
    int iVal3 = int.Parse("10120"); // throws exception value cannot be null;

    // handles null converts null to 0
    // does not handle NAN ("102art54") (throws exception)
    // converts obj to int ("26236")
    int val4 = Convert.ToInt32("10120"); 

    // handle null converts null to 0
    // handle NAN ("101art54") converts null to 0
    // convert string to int ("26236")
    int number;

    bool result = int.TryParse(value, out number);

    if (result)
    {
        // converted value
    }
    else
    {
        // number o/p = 0
    }
Найас Субраманян
источник
2
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
Tohid
источник
1
Я нашел этот ответ действительно полезным, я искал преобразовать упакованный байт в int и заставил его работать с использованием Convert.ChangeType. Я бы сказал, что не может быть идеальным ответом для ОП, но это определенно полезно для некоторых!
Филипп Паре
1

Также есть TryParse .

Из MSDN:

private static void TryToParse(string value)
   {
      int number;
      bool result = Int32.TryParse(value, out number);
      if (result)
      {
         Console.WriteLine("Converted '{0}' to {1}.", value, number);         
      }
      else
      {
         if (value == null) value = ""; 
         Console.WriteLine("Attempted conversion of '{0}' failed.", value);
      }
   }
Лэнс Харпер
источник
1

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

Итак, если у меня есть переменная типа object, а у «коробочного» класса есть определенные неявные операторы, они не будут работать.

Вместо этого еще один простой способ, но на самом деле снижение производительности - это приведение в динамическом режиме.

(INT) (динамическая) MyObject.

Вы можете попробовать это в Интерактивном окне VS.

public class Test
{
  public static implicit operator int(Test v)
  {
    return 12;
  }
}

(int)(object)new Test() //this will fail
Convert.ToInt32((object)new Test()) //this will fail
(int)(dynamic)(object)new Test() //this will pass
eTomm
источник
1
это действительно так , но вы определенно захотите, чтобы вы в профиле, если вы делаете это много - dynamicдалеко не бесплатно
Марк Грэвелл
@MarcGravell Я полностью согласен с вами, как я также написал в ответе.
eTomm