2011-06-06 16 views
0

我开始使用泛型,并且无法真正地找到简单的初学者指南,所以我只是在做试验和错误。如何在泛型中做到这一点?

我想转换此

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); 

回答

1

现在什么混淆了赫克了我的我是怎么投“实体”到一个Task对象,但现在只有它,但我需要转换的其他对象像需要时区的约会。

如果您使用的是泛型,则不需要施放。或者换一种说法:你使用泛型的原因是因为你不想投射。为了说明这一点,下面是MSDN的An Introduction to C# Generics的摘录。

因为通用代码不会强制对值类型进行装箱和拆箱,或者对引用类型进行向下转换,所以性能会大大提高。

一般来说,仿制药具有以下优点:

  • 提高性能
  • 强制类型安全
  • 可重复使用的

如果您需要更具体的例子,看看(及对比)ArrayList and 列表(T)(在MSDN中搜索它们)。对于添加方法,的ArrayList具有以下特征:

public virtual int Add(Object value)

名单(T)相同的方法被定义为:

public void Add(T item)

因此,可以看到泛型方法接受任何类型(可重用),并以类型安全的方式处理类型,而无需投射(提高性能)。当然,ArrayList也是可重用的,但您需要对其进行铸造,使其更加安全并且性能更差。

话虽如此,我上一段实际上有一个困惑。尽管您可以使用泛型来处理任何类型,但您也可以实现一个约束来使泛型参数实现特定的接口,从而将泛型参数限制为某些类(实现接口的那些类)。在前面提到的“C#泛型简介”中可以找到更深入的主题(通用约束)。

至于代码示例,@Ed S.实际上显示了一种可行的方法。 (参考@Ed S的代码示例)通过使用通用约束,参数因此被限制为实现IEntity的类,其接口具有ConvertToUtcTime方法。

9

你需要通过一个公共接口工作,如果要访问属性或第一个参数的方法。无论如何,你不想在一般的方法里面投射。如果这些实体从一个共同的基类派生或实现一个共同的接口,你可以使用一个通用的限制和工作贯穿其中:

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); 
} 
+0

@Ed S. - 你能举出更多更完整的例子吗?首先什么是“T:IEntity”?其次是你在不同的接口实现中传递什么?就像说一次我正在传递一个任务,ConverToUtcTime如何处理这个问题?那么下一次我通过DateTime时,它会怎样呢? – chobo2 2011-06-06 01:31:10

+0

“其中”仅仅是泛型类型的限制。这意味着“我只想允许T *类型的T *是一个'IEntity'” – Marlon 2011-06-06 01:33:52

+0

@Marlon - 所以如果我想将任务传递到这个方法中,我不能? – chobo2 2011-06-06 01:34:46