Приведение объекта, содержащего int, к float приводит к InvalidCastException

#c#

#c#

Вопрос:

 protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    var fP18VaR = (float) (int)e.Values[0];
}
 

Я получаю

Приведение, указанное в InvalidCastException, недопустимо

Почему это не работает?

Значение e.Values[0] равно: 6 666,00

Комментарии:

1.Что такое e.Values[0] , a Horse ? Редактировать Так оно и есть 6 666,00 , десятичное / двойное число или a string ?

2. Может быть, приведение к int уже завершается неудачей?

3. например, значения [0]. GetType()?

4. Я согласен с @UweKeim .. Я думаю, что значения связаны с каким-то другим типом данных.

5. действительно ли это 6 [пробел] 666,00 ? Если это так, анализ int, вероятно, уже завершается с ошибкой

Ответ №1:

Проблема, с которой вы сталкиваетесь здесь, заключается в том, что оператор приведения C # означает разные вещи в разных ситуациях.

Возьмите этот пример, который вы привели:

 object num = 10;
float fnum = (float)num;
 

Компилятор C # подумает, что вы говорите ему следующее: «Переменная num ссылается на значение с плавающей запятой в штучной упаковке; пожалуйста, распакуйте его и верните значение в штучной упаковке».

Вы получаете сообщение об ошибке, потому что это не штучный float, а штучный int .

Проблема в том, что C # использует идентичный синтаксис для двух совершенно не связанных операций: ‘unbox’ и ‘числовое преобразование’. Вот пример того, где приведение означает числовое преобразование:

 int num = 10;
float fnum = (float)num;
 

Почти точно такой же код, и все же это не выдаст вам ошибку. И это потому, что компилятор C # обрабатывает это совершенно по-другому — этот код означает: «Пожалуйста, выполните числовое преобразование, преобразуя целое число, хранящееся в ‘num’, в значение с плавающей запятой одинарной точности».

Как вы узнаете, какую из этих двух совершенно не связанных операций он выберет? Все дело в типах источника и назначения. Если вы преобразуете из ‘object’ в тип значения, это всегда будет рассматриваться как unbox . Если вы преобразуете из одного числового типа в другой, это всегда будет рассматриваться как числовое преобразование.

Итак, как вы получаете желаемый результат? Ну, вам нужно выполнить обе операции: вам нужно распаковать int, а затем преобразовать его в значение с плавающей точкой. Итак, вам действительно нужно два приведения:

 object num = 10;
float fnum = (float) (int)num; 
 

Ужасно, да?

Самый простой способ сделать то, что вы хотите здесь, — полностью избежать приведения. Просто сделайте это:

 float fnum = Convert.ToSingle(num); 
 

Это принудит тип к одинарной точности с плавающей точкой, если это возможно.

Ответ №2:

Тип времени компиляции e.Values[0] is Object . Итак, вам действительно нужно выполнить приведение и / или преобразование, чтобы получить float . Если

 (int)e.Values[0]
 

завершается успешно, затем

 (float) (int)e.Values[0]
 

добьется успеха. Следовательно, e.Values[0] не может быть преобразован в int .

Ваш следующий шаг — определить, что такое тип и значение среды выполнения e.Values[0] , и попытаться понять, как преобразовать это в числовое значение.

Ответ №3:

Ваше приведение недопустимо, потому что e.Values[0] возвращает значение в штучной упаковке как объект, который сначала необходимо привести к исправлению базового типа. Чтобы преобразовать базовое значение в значение с плавающей запятой, сначала необходимо указать правильный тип.

Кроме того, если object — это не тип значения, а какой-то другой контейнер или, например, string — вам нужно сначала привести к этому контейнеру, а затем найти способ преобразовать это в float .

У Эрика Липпера есть отличная статья на эту тему: Представление и идентификация.

Ответ №4:

Рассмотрите возможность использования TryParse вместо этого; немного подробный пример ниже, чтобы дать вам представление о том, как обрабатывать синтаксический анализ ошибок и как впоследствии преобразовать нулевое значение с плавающей точкой в обычное:

 protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    float? temp;
    if (!float.TryParse(e.Values[0], out temp))
    {
        //code to handle problems parsing here
        throw new InvalidCastException("Invalid cast: '{0}' cannot be parsed to a float", e.Values[0]);
    }
    //if we reach here (we've not thrown an error above), `temp` is not null
    var fP18VaR = temp.Value;
}
 

ПРИМЕЧАНИЕ: эта функция учитывает текущую культуру; поэтому, если вы работаете с мультикультурными данными, вам нужно знать, в каком формате находятся цифры. Видишь http://msdn.microsoft.com/en-us/library/3s27fasw (v = против 110).aspx для получения дополнительной информации.