简体   繁体   English

泛型类型参数的调用方法

[英]Call method on parameter of generic type

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? 如何在列表项上调用Reset()

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. 然而,缺少的是,就目前而言,编译器不知道每个T是否具有reset()方法。 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. 因此,您必须向T参数添加一个约束 ,该约束需要T来实现接口或从声明这种reset()方法的类继承。

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 . 这强制传递给T类型参数的任何类型都必须实现IThing In return, the compiler can guarantee that point in your method actually has a reset() method that you can invoke. 作为回报,编译器可以保证方法中的point实际上具有可以调用的reset()方法。

If your question is "How can I call Reset() on T " , then - to do it properly - you need to introduce a generic type constraint . 如果您的问题是“如何在T上调用Reset() ,那么 - 要正确地执行 - 您需要引入泛型类型约束

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 . 现在,当您调用ResetPointProperties()方法时,必须使用List<T>的参数,其中T实现接口IResettable For example a Point class: 例如一个Point类:

public class Point : IResettable
{
    public void Reset()
    {
        X = 0;
        Y = 0;
    }
}

Ok, let's have a look at all possible ways of getting it to work : 好的,让我们看一下让它运行的所有可能方法:

A. Generic constraints A.通用约束

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 : B.在调用方法之前键入检查和显式转换:

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 : C.通过反射:

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 : D.使用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). 接下来将是强制转换然后执行某些操作(例如,在类是来自某个外部dll并且您无法控制它的情况下)。 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... 想象一下,这40个模型中每个模型都有40个数据库模型和3个视图模型,你想用某种方法映射它们......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM