我开始使用泛型并且无法真正找到简单的初学者指南,所以我只是在做试验和错误。
我想转换此
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;
}
现在让我感到困惑的是如何将“实体”转换为Task对象,但现在仅将其转换为我需要转换的其他对象,如需要时区的约会。
我无法弄清楚如何让它为我所有不同的物体转换不同的时区。
修改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);
答案 0 :(得分: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);
}
答案 1 :(得分:1)
现在让我感到困惑的是如何将“实体”转换为Task对象,但现在仅将其转换为我需要转换的其他对象,如需要时区的约会。
如果你使用泛型,你不需要施放。或者换一种说法:你使用泛型的原因是因为你不想投。为了说明这一点,以下是MSDN An Introduction to C# Generics的摘录。
由于通用代码不强制对值类型进行装箱和取消装箱,或者对引用类型进行向下转换,因此性能会大大提高。
一般而言,仿制药具有以下优点:
如果您需要更具体的示例,请查看(并比较) ArrayList 和 List(T)(在MSDN中搜索它们)。对于add方法, ArrayList 具有以下签名:
public virtual int Add(Object value)
List(T)的相同方法定义为:
public void Add(T item)
因此,您可以看到泛型方法采用任何类型(可重用),并以类型安全的方式处理该类型,而无需强制转换(提高性能)。当然, ArrayList 也是可重用的,但是你需要对它进行强制转换,使它的类型安全性降低,性能更差。
话虽如此,我之前的段落确实存在混淆。虽然您可以使用泛型来处理任何类型,但您也可以实现约束以使通用参数实现特定接口,从而将泛型参数限制为某组类(实现接口的类)。更深入地了解该主题(通用约束)可以在前面提到的C#Generics简介中找到。
至于代码示例,@ Ed S.实际上已经展示了一种可行的方法。 (参考@Ed S的代码示例。)通过使用泛型约束,该参数因此仅限于实现 IEntity 的类,其接口具有 ConvertToUtcTime 方法。