Reputation: 21
I want to write a generic method that as input has a list of generic objects. I want to call a method on each of the list items.
What I'm trying to do is writing something like:
public void ResetPointProperties<T> (List<T> Points)
{
foreach (T point in Points)
{
point.Reset();
}
}
How can I call Reset()
on my list items?
Upvotes: 2
Views: 138
Reputation: 13676
Ok, let's have a look at all possible ways of getting it to work :
A. Generic constraints
public void ResetPointProperties<T> (List<T> Points)
where T : ISomeInterface // interface must contain .Reset method
{
foreach (T point in Points)
point.Reset();
}
B. Type check and explicit convertion before calling method :
public void ResetPointProperties<T> (List<T> Points)
{
if(typeof(T) != typeof(Point)) return;
foreach (T point in Points)
{
Point p = point as Point;
p.Reset();
}
}
C. Via reflection :
public void ResetPointProperties<T> (List<T> Points)
{
if(typeof(T) != typeof(Point)) return;
MethodInfo method = typeof(T).GetMethod("Reset");
foreach (T point in Points)
{
t.Invoke(point, null);
}
}
D. Using dynamic
:
public void ResetPointProperties<T> (List<T> Points)
{
foreach (dynamic point in Points)
{
point.Reset();
}
}
If it's possible the best solution is to use interface and generic constraints. Next would be casting and then doing something (for example in scenario when class is from some external dll and you dont have control over it). Reflection and dynamics are generally not recommended, as they're slow, and almost impossible to unit-test.
But sometimes using of reflection and dynamics may solve some considerable time with some complicated scenarios.
Imagine you have 40 models in database and 3 viewmodel for each of this 40 models and you want to map them in some method...
Upvotes: 1
Reputation: 151588
If your question is "How can I call Reset()
on T
", then - to do it properly - you need to introduce a generic type constraint.
You can do so using an interface:
public interface IResettable
{
void Reset();
}
And apply that:
public void ResetPointProperties<T> (List<T> Points)
where T : IResettable
Now when you call the ResetPointProperties()
method, you must do so with an argument of List<T>
where T
implements the interface IResettable
. For example a Point
class:
public class Point : IResettable
{
public void Reset()
{
X = 0;
Y = 0;
}
}
Upvotes: 4
Reputation: 20720
You are almost there. However, what is missing is that as it stands, the compiler does not know whether/that each T
has a reset()
method. Therefore, you will have to add a constraint to the T
parameter that requires T
to implement an interface or inherit from a class that declares such a reset()
method.
For instance, let's assume you somewhere have the following interface:
public interface IThing
{
void reset();
}
Then, you could declare your above method as follows:
public void ResetPointProperties<T> (List<T> Points)
where T : IThing
This enforces that any type passed to the T
type parameter must implement IThing
. In return, the compiler can guarantee that point
in your method actually has a reset()
method that you can invoke.
Upvotes: 5