我想编写一个通用方法,作为输入有一个通用对象列表。我想在每个列表项上调用一个方法。
我正在尝试做的事情是:
public void ResetPointProperties<T> (List<T> Points)
{
foreach (T point in Points)
{
point.Reset();
}
}
如何在列表项目上调用Reset()
?
答案 0 :(得分:5)
你快到了。但是,缺少的是,就目前而言,编译器不知道每个T
是否具有reset()
方法。因此,您必须向T
参数添加constraint,该参数需要T
来实现接口或从声明此类reset()
方法的类继承。
例如,让我们假设你某处有以下界面:
public interface IThing
{
void reset();
}
然后,您可以按如下方式声明上述方法:
public void ResetPointProperties<T> (List<T> Points)
where T : IThing
这会强制传递给T
类型参数的任何类型必须实现IThing
。作为回报,编译器可以保证方法中的point
实际上具有可以调用的reset()
方法。
答案 1 :(得分:4)
如果您的问题是“如何在Reset()
上致电T
,那么 - 要正确地执行此操作 - 您需要引入generic type constraint。
您可以使用界面执行此操作:
public interface IResettable
{
void Reset();
}
并申请:
public void ResetPointProperties<T> (List<T> Points)
where T : IResettable
现在,当您调用ResetPointProperties()
方法时,必须使用List<T>
参数,其中T
实现接口IResettable
。例如Point
类:
public class Point : IResettable
{
public void Reset()
{
X = 0;
Y = 0;
}
}
答案 2 :(得分:1)
好的,我们来看看让它发挥作用的所有可能方法:
:一种。通用约束
public void ResetPointProperties<T> (List<T> Points)
where T : ISomeInterface // interface must contain .Reset method
{
foreach (T point in Points)
point.Reset();
}
<强> B中。在调用方法之前键入check和explicit convertion:
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();
}
}
<强>℃。通过反思:
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。使用dynamic
:
public void ResetPointProperties<T> (List<T> Points)
{
foreach (dynamic point in Points)
{
point.Reset();
}
}
如果可能,最好的解决方案是使用接口和通用约束。接下来将是强制转换然后执行某些操作(例如,在类是来自某个外部dll并且您无法控制它的情况下)。通常不推荐反射和动力学,因为它们很慢,几乎不可能进行单元测试。
但有时使用反射和动力学可能会在一些复杂的情况下解决相当长的时间。
想象一下,这40个模型中每个模型都有40个数据库模型和3个视图模型,你想用某种方法映射它们......