C#:Приведение объекта к числовому типу без знака с использованием дженериков

StackOverflow https://stackoverflow.com/questions/773971

  •  13-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь написать некоторый код для преобразования данных из поля типа объекта (поступающих из набора данных) в его целевые (типизированные) поля.Я делаю (по крайней мере, пытаюсь) это, используя динамическое преобразование.Кажется, это нормально работает для строк, int, DateTime.

Но это не работает для неподписанных типов (ulong, uint).Ниже есть простой код, который показывает, что я хочу сделать.Если вы измените тип ul var с ulong на int, это будет работать нормально.

У кого-нибудь есть ключ к разгадке?

public class console
{

    public static void CastIt<T>(object value, out T target)
    {
        target = (T) value;
    }

    public static void Main()
    {
        ulong ul;
        string str;
        int i;
        DateTime dt;

        object ul_o = (object) 2;
        object str_o = (object) "This is a string";
        object i_o = (object)1;
        object dt_o = (object) DateTime.Now;

        Console.WriteLine("Cast");

        CastIt(ul_o, out ul);
        CastIt(str_o, out str);
        CastIt(i_o, out i);
        CastIt(dt_o, out dt);

        Console.WriteLine(ul);
        Console.WriteLine(str);
        Console.WriteLine(i);
        Console.WriteLine(dt.ToString());
    }

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

Решение

Как говорит Эндрю, проблема в том, что вы не можете распаковать коробку из упакованного int Для ulong.

Два варианта:

1) Вставка а ulong вместо этого:

object ul_o = (object) 2UL;

или

ulong tmp = 2;
object ul_o = tmp;

2) Сделать CastIt<T> использование Convert.ChangeType:

public static void CastIt<T>(object value, out T target)
{
    target = (T) Convert.ChangeType(value, typeof(T));
}

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

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

Это потому, что ваш объект ul_o является int, а не числом без знака.Когда вы находитесь в своей функции приведения, вы выполняете приведение, имея целевые данные в контексте object.Явные / неявные операторы приведения (это то, что вам нужно было бы использовать) работают только тогда, когда у вас есть объект в контексте типа, который их реализует (поскольку эти операторы статически связаны во время компиляции, а не динамически во время выполнения).

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

target = (T)Convert.ChangeType(value, typeof(T));

Среда CLR не позволяет вам приводить значения таким образом, потому что ваш тип значения в штучной упаковке на самом деле является int:

object ul_o = (object)2;

Когда вы пытаетесь выполнить приведение к ulong вы не можете, потому что вы не можете распаковать int непосредственно в ulong.

Я думаю, то, что вы хотите, больше похоже (непроверенное, но направленно правильное)...

public static void CastIt<T>( object value ) where T : IConvertable
{
  return ( T )Convert.ChangeType( value , typeof( T ) );
}

Редактировать:Схвачен Скитом!:)

На самом деле это не ответ на ваш вопрос;Просто хотел упомянуть, что если вы используете .Net 3.5, то Ссылка на наборы данных код включает в себя функциональность, подобную той, которую вы реализуете.Конкретным методом расширения будет Field<T>() в классе DataRow.

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