Как это сделать в дженериках? - PullRequest
0 голосов
/ 06 июня 2011

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

Я хочу преобразовать это

public void CreateTask(Task task, Student student)
{
            Task convertToUtcTime = task.ConvertToUtcTime(student);
            session.Save(convertToUtcTime);
}


public static Task ConvertToUtcTime(this Task task, Student student)
{
    if (student != null)
    {
        TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(student.TimeZoneId);
        task.DueDate = TimeZoneInfo.ConvertTimeToUtc(task.DueDate, info);
    }

    return task;
}

чтобы быть общим

Я начал пробовать это (я еще не выполнил это, так что это может даже не сработать)

  public void Create<T>(T entity, Student student)
    {
                T convertToUtcTime = entity.ConvertToUtcTime(student);
                session.Save(convertToUtcTime);
    }


  public static T ConvertToUtcTime(this T entity, Student student)
    {
        if (student != null)
        {
            TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(student.TimeZoneId);
            entity.DueDate = TimeZoneInfo.ConvertTimeToUtc(entity.DueDate, info);
        }

        return entity;
    }

Теперь что меня смущает, так это как я разыгрываю«сущность» в объект «Задача», но теперь только это, но другие объекты, которые мне нужно преобразовать, например, «Назначение», которому нужен часовой пояс.

Я просто не могу понять, как я могу заставить его преобразовывать разные временные зоны для всехмои разные объекты.

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

// also used with nhibernate hence why everything is virtual
    public class Task :IEntity
{
    public virtual int TaskId { get; private set; }
    public virtual DateTime DueDate { get; set; }


    public virtual Task ConvertToUtcTime2(Student student)
    {
        DateTime s = DueDate ;
        // not use to returning "this" but seems only way how to get the object back.
        // I also realized I can do this as well 
        this.ConvertToUtcTime(Student); // So I am still using my extension method and no need to duplicate that code.
        return this;
    }
}

 public interface IEntity
    {
        IEntity ConvertToUtcTime2(Student student);
        // more methods/properties
    }

  public void Create<T>(T entity, Student student) where T: IEntity
        {
            entity.ConvertToUtcTime2(student);
        }

   // call generic method.
   nhibernateRepo.Create(task, student);

Ответы [ 2 ]

9 голосов
/ 06 июня 2011

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

public interface IEntity
{
    IEntity ConvertToUtcTime(Student);
    // more methods/properties
}

public void CreateTask<T>(T entity, Student student) where T : IEntity
{
    T convertToUtcTime = entity.ConvertToUtcTime(student);
    session.Save(convertToUtcTime);
}
1 голос
/ 06 июня 2011

Теперь, что меня смущает, так это то, как я преобразую «сущность» в объект «Задача», но теперь только в этот объект, но в другие объекты, которые мне нужно преобразовать как назначение, которому нужен часовой пояс.

Вам НЕ нужно кастовать, если вы используете дженерики.Или сформулируйте это по-другому: причина, по которой вы используете дженерики, заключается в том, что вы не хотите разыгрывать.Чтобы проиллюстрировать это, ниже приведен отрывок из Введение в C # Generics MSDN.

Поскольку общий код не вызывает блокировку и распаковку типов значений илиПри приведении ссылочных типов производительность значительно улучшается.

В общем, дженерики имеют следующие преимущества:

  • повышает производительность
  • обеспечивает безопасность типов
  • многоразовый

Если вам нужен более конкретный пример, посмотрите (и сравните) ArrayList и List (T) (найдитеих в MSDN).Для метода добавления ArrayList имеет следующую подпись:

public virtual int Add(Object value)

Тот же метод List (T) определяется как:

public void Add(T item)

Таким образом, вы можете видеть, что универсальный метод принимает ЛЮБОЙ тип (многоразовый) и работает с типом безопасным для типов способом без необходимости приведения (улучшаетспектакль).Конечно, ArrayList также можно использовать многократно, но вам нужно выполнить наложение на него, сделать его менее типичным и иметь худшую производительность.

Сказав это, мой предыдущий абзац на самом деле имеетспутанность сознания.Хотя вы можете использовать generic для работы с ЛЮБЫМ типом, вы также можете реализовать ограничение для универсального параметра, реализующего конкретный интерфейс, ограничивая таким образом универсальный параметр определенным набором классов (тех, которые реализуют интерфейс).Более подробный взгляд на эту тему (Общие ограничения) можно найти в разделе Введение в общие черты C #, упомянутом ранее.

Что касается примера кода, @Ed S. на самом деле показал жизнеспособный путь.(Обратимся к примеру кода @Ed S.) Благодаря использованию общих ограничений параметр ограничивается классами, которые реализуют IEntity , интерфейс которого имеет метод ConvertToUtcTime .

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