C # универсальное исключение приведения - PullRequest
6 голосов
/ 16 марта 2011

Я столкнулся со странной проблемой при использовании дженериков.Следующий код выдаст InvalidCastException, хотя ясно, что int может быть приведен к double.Кто-нибудь может объяснить это поведение и как его обойти?

public class TestClass<T>
{
    public T Cast(object o)
    {
        return (T)o;
    }
}

public void Main()
{
    TestClass<double> w = new TestClass<double>();
    double x = w.Cast(10);
}

Редактировать:

Так как я нахожусь в .net 4.0 land, я все же изменил его, чтобы использовать 'динамический »вместо« объект », и все работает, как ожидалось.Цените все оперативные и быстрые ответы.

Ответы [ 7 ]

9 голосов
/ 16 марта 2011

Но object нельзя привести к double. Параметр o принимает object, а не int.

Например, следующий код завершается с InvalidCastException:

 object o = 1000;
 double x = (double)o;
6 голосов
/ 16 марта 2011

Вы можете использовать TypeConverter для преобразования переменных

        public class TestClass<T>
        {
            public T Cast(object o)
            {
                TypeConverter converter = TypeDescriptor.GetConverter(o);
                if (converter.CanConvertTo(typeof(T)))
                {
                   var result = converter.ConvertTo(o, typeof(T));
                   return (T)result;
                }

                throw new InvalidCastException(
                      string.Format("Cannot convert from {0} to {1}", o.GetType().Name, typeof(T).Name));
            }
        }
1 голос
/ 16 марта 2011

Это будет работать

        object y = 10;
        Double v = (int) y;

это не будет

        object y = 10;
        Double v = y;

потому что оно должно быть приведено явно.

1 голос
/ 16 марта 2011

Параметр «o» в Cast приведен в штучной упаковке. Видимо, вы не можете разыграть упакованный int в двойник без коробки. Смотрите здесь .

Если бы вы знали, что внутри функции Cast было бы int, вы могли бы сделать:

return (double)((int)o);

Я не знаю о случае неизвестного типа. Проверка.

РЕДАКТИРОВАТЬ: изменить T на удвоение

0 голосов
/ 16 марта 2011
 public T Cast(object o)
 {
     return (T)Convert.ChangeType(o, typeof (T));

 }

Хотя я не уверен, почему.

0 голосов
/ 16 марта 2011

Вы можете обойти это, выполнив:

public class TestClass<T>
{
    public T Cast<T2>(T2 o)
    {
        return (T)o;
    }
}

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

0 голосов
/ 16 марта 2011

Я предполагаю, что это потому, что int нельзя привести к двойному, но есть явное преобразование к двойному.Который должен быть определен по типу.Так как ваш объект Cast не знает, будет ли данный тип иметь это преобразование, он пытается выполнить базовое приведение и терпит неудачу.

...