Преобразовать тип объекта в DateTimeOffset - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть словарь строк и объектов, для целочисленной части я могу использовать Convert.ToInt32 (), но для DateTimeOffset я не могу найти ни одного (есть Convert.ToDateTime (), но я боюсь, что смещениечасть будет обрезана), я попытался выполнить поиск в стеке потока и в Интернете, но ничто не может быть использовано.

Пожалуйста, помогите.

Обновление:

Как инициализировать окно словаря и просмотрарезультат.StoreID - это int, другой - DateTimeOffset.

enter image description here

1 Ответ

0 голосов
/ 18 сентября 2018

Во-первых, я думаю, что хранение нескольких типов данных, как это, вероятно, плохая идея - альтернативы см. Ниже. C # строго типизирован (по большей части) и работает лучше всего, когда знает заранее, что происходит с типами. Но у него есть способы определения того, какой тип на самом деле хранится в object, и позволяет вам возвращаться к соответствующим типизированным ссылкам.

В этом случае лучше всего подходит для вашей проблемы оператор is . Это позволит вам проверить, совместим ли object (или ссылка, или ...) с указанным типом:

object val = task.Data["StartDate"];
if (val is DateTimeOffset)
{
    var dto = (DateTimeOffset)val;
    // do something with the DateTimeOffset
}

В C # версии 7 они представили вариант сопоставления с образцом, который позволяет сокращать преобразование типов:

object val = task.Data["StartDate"];
if (val is DateTimeOffset dto)
{
    // do something
}

Это работает как для ссылочных типов, так и для типов значений, и будет проходить любой действительный неконвертирующий тип преобразования. Это также удобно для тестирования интерфейсов типов в общем коде:

if (someobject is IDisposable disp)
{
    disp.Dispose();
}

В общем, я бы по возможности избегал вашего словаря объектов. Хотя есть некоторые случаи, когда это действительно, эти случаи довольно редки. Например, ViewBag в ASP.NET MVC - один из случаев, когда он работает, но есть и другие способы, которые можно было бы сделать.

Причина проста: для упаковки и распаковки значений требуется время . Тестирование типов значений требует времени, которое вам больше не нужно тратить, если вы используете статические типы. И вам не нужно беспокоиться о том, что кто-то вставит строку, где вы ожидаете int.

Для вашего собственного кода более нормальным случаем было бы определить класс для хранения данных задачи и передать это:

public class TaskData
{
    public int StoreID { get; set; }
    public DateTimeOffset StartDate { get; set; }
}

... и использовать его как:

task.Data = new TaskData { StoreID = storeID, startDate = DateTimeOffset.Now.AddDays(3) };

Теперь ваша задача будет знать, с чем имеет дело напрямую, не требуется кастинг. И нет никаких шансов, что кто-то придет и назначит какое-то дурацкое значение, с которым ваш код не знает, как обращаться с одной из ваших переменных. Или забудьте о DateTimeOffset и используйте DateTime вместо этого, без каких-либо жалоб со стороны компилятора.

Если вы действительно не хотите определять все виды классов только для такого рода вещей, вы можете использовать типы C # 7 Tuple , чтобы сделать нечто подобное:

// in your task class:
public (int StoreID, DateTimeOffset StartDate) Data { get; set; }

// initialize in other code:
task.Data = (storeID, DateTimeOffset.Now.AddDays(3));

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

Конечно, если вам действительно необходимо использовать Dictionary<string, object> для этих данных, тогда продолжайте. Просто спросите себя, стоит ли накладные расходы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...