.NET недопустимое приведение исключения при двойном делении

2

Я работаю над .NET-приложением, чтобы уменьшить размеры файлов изображений, используя ImageMagick. В моем приложении хранятся некоторые "настройки" в Hashtable для использования в различных областях приложения. Теперь я добавляю функцию для уменьшения размера изображения на основе желаемого DPI в преобразованном изображении. В принципе, я просматриваю DPI в неизмененном изображении, вычисляя процентное соотношение желаемого DPI относительно текущего DPI, а затем я изменяю размеры изображения по этой пропорции.

ImageMagick передает изображение DPI как значения с плавающей запятой. Итак, 200x200 DPI действительно 199.975x199.975. Таким образом, я использую Math.Ceiling(), чтобы получить значения в моем приложении. Когда я пытаюсь использовать желаемый DPI из моих настроек Hashtable, чтобы выполнить вычисление процента, я получаю недопустимое исключение литых. Я не знаю, почему это происходит.

Вот пример, который терпит неудачу так же, как мой фактический код:


using System;
using System.Collections;

namespace typetest
{
    class Program
    {
        private struct DPI {
            public double x;
            public double y;
        }

        public static void Main(string[] args)
        {
            Hashtable vars = new Hashtable();
            DPI dpi;
            string dpiString = "199.547:199.547";
            string[] ret;

            vars["newDpiX"] = 150;
            vars["newDpiY"] = 150;
            ret = dpiString.Split(':');

            dpi.x = ( (double)vars["newDpiX"] / Math.Ceiling(double.Parse(ret[0])) ) * 100;
            dpi.y = ( (double)vars["newDpiY"] / Math.Ceiling(double.Parse(ret[1])) ) * 100;

            Console.WriteLine("New DPI percentage = " + dpi.x + "%x" + dpi.y +"%");
        }
    }
}

Если я изменю деление на


double newDpiX = 150.0;
dpi.x = ( newDpiX / Math.Ceiling(double.Parse(ret[0])) ) * 100;

он будет работать, как ожидалось. Что здесь происходит?

Теги:

4 ответа

5
Лучший ответ

В Hashtable хранятся объекты. Когда вы помещаете int в объект, вы "вставляете" его. Unboxing требует того же типа, вы не можете преобразовать непосредственно из вложенного int в double.

Это не удастся:

object obj = 10;
double dbl = (double)obj;

Это будет успешным:

object obj = 10d; // a double value, could also have been 10.0
double dbl = (double)obj;

И это также будет работать:

object obj = 10; // an int
double dbl = (double)(int)obj;

сначала распаковывая int, и только затем сбрасывая double.

EDIT:

См. также http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx

  • 0
    Это на самом деле объясняет, чего мне не хватало. Спасибо.
3

Попробуйте

vars["newDpiX"] = 150d;
  • 0
    Разве 150d не будет рассматривать 150 как десятичную, а не как двойную?
  • 0
    150 м будет десятичным.
1

Использование:

dpi.y = ( Convert.ToDouble(vars["newDpiY"]) / Math.Ceiling(double.Parse(ret[1])) ) * 100;

Я думаю, ваша проблема в том, что vars [ "newDpiY" ] = 150; хранит int, а не double.

  • 0
    Хорошо, это работает, если я явно сохраню 150 как двойное число в хеш-таблице. Но почему я не могу указать приведение во время деления (без использования Convert)?
  • 0
    с броском вы должны были бы сделать (double) (int) .. чтобы сначала преобразовать в то, чем он является на самом деле, а затем удвоить.
0

Объекты Hashtable hold, вам назначается 150, поэтому он хранится как int. Попробуйте назначить 150.0 или (double) 150 или что-нибудь в этом роде.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню