I am starting to use generics and been unable to really find the simple beginners guide to them yet so I am just doing trial and error.
I want to convert this
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;
}
to be generic
I started trying this(I have no complied it yet so this might not even work)
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;
}
Now what confuses the heck out of me is how do I cast “entity” to a Task object but now only that but other objects that I need to convert like an Appointment that needs a timezone.
I just can’t figure out how I could make it convert different timeszones for all my different objects.
Edit 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);
You DO NOT need to cast if you are using generics. Or put this in another way: the reason you are using generics is because you do not want to cast. To illustrate this, below is an excerpt from An Introduction to C# Generics of MSDN.
In general, generics has the following benefits:
If you need a more specific example, look at (and compare) ArrayList and List(T) (search for them in MSDN). For the add method, ArrayList has the following signature:
public virtual int Add(Object value)The same method of List(T) is defined as:
public void Add(T item)Thus, you can see that a generic method takes in ANY type (reusable), and works on the type in a type-safe manner without the need to cast (improves performance). Of course, ArrayList is also reusable, but you need to do casting on it, making it less type-safe and has worse performance.
Having said that, my previous paragraph actually has a confusion. While you do can make use of generic to work on ANY type, you can also implement a constraint to have the generic parameter implementing a particular interface, thus limiting the generic parameter to a certain set of classes (those that implement the interface). A more in-depth look at the topic (Generic Constraints) can be found in An Introduction to C# Generics mentioned previously.
As for code sample, @Ed S. has actually showed a viable way. (Referring to the code sample of @Ed S.) Through the use of generic constraints, the parameter is thus limited to classes that implement IEntity, an interface of which has a ConvertToUtcTime method.