在Generic上调用实例方法的委托

时间:2011-03-25 14:14:43

标签: c# .net linq generics delegates

我没有太多运气寻找这个答案,因为我认为我对它的正确用语知之甚少。

(编辑代码的清晰度以及我如何调用它)

我有一个实例化扩展方法的类:

public static class Foo
{
    public static IList<T> Bar<T>(this DataTable table) where T : class, new()
    {
        IList<T> list = ... // do something with DataTable.

        return list;
    }
}

我这样称呼这个方法:

DataTable table = SomehowGetTable();

IList<MyObject> list = table.Bar<MyObject>();

再次,大大简化。

现在,我想做的是添加一个委托(?),以便在我获得列表后,我可以在列表中的每个T上调用一个方法,如下所示:

public static class Foo
{
    public static IList<T> Bar<T>(this DataTable table, MyDelegate postProcess)
    {
        IList<T> list = ... // do something with DataTable.

        foreach(T item in list)
        {
            t.postProcess();
        }

        return list;
    }
}

我不知道我需要能够传递postProcess ..委托,谓词或动作,主要是因为我仍然是Linq挑战。

或者,这可能甚至不可能?

5 个答案:

答案 0 :(得分:3)

你想要的是一个动作&lt; T>所以你可以这样做:

public static class Foo
{
    public static IList<T> Bar(this DataTable table, Action<T> postProcess)
    {
        IList<T> list = ... // do something with DataTable.

        foreach(T item in list)
        {
            postProcess(item);
        }

        return list;
    }
}

答案 1 :(得分:2)

首先,您需要将Bar定义为通用,否则将无法编译。

其次,如果您尝试对列表中的每个元素进行操作,则需要传入一个带有T类型的单个参数的委托,并且不返回任何值。内置的.NET委托类型为Action<T>,它会很好。

所以,

public static IList<T> Bar<T>(this DataTable table, Action<T> postProcess)
{
    IList<T> list = ... // do something with DataTable

    foreach(T item in list)
    {
        postProcess(item);
    }

    return list;
}

答案 2 :(得分:1)

签名将是

public static IList<T> Bar<T>(this DataTable table, Action<T> postProcess) {
  var list = // Get ILIst<T> from DataTable
  foreach (var i in list)
  postProcess(i);
}

现在.Net几乎将所有方法签名带到了ActionFunc代表可能需要的表格中。虽然action包含所有void返回类型方法,但Func引入了非void返回。

请注意,必须将T定义为方法的类型参数。编译器可能能够从您提供给方法的操作中推断出T:

List<double> myDoubles = table.Bar((double x) => Debug.Writeline(x));

例如,如果您实际处理的是不同类型的值,则签名可能如下所示:

public static IList<Z> Bar<T,Z>(this DataTable table, Func<T,Z> postProcess) {
  return /* Get Listof T */ .Select(postProcess).ToList();
}

一样使用
List<int> values = table.Bar((double d) => (int)d);

答案 3 :(得分:1)

尝试Action<T>

public static class Foo
{
    public static IList<T> Bar(this DataTable table, Action<T> postProcess)
    {
        IList<T> list = ... // do something with DataTable.

        foreach(T item in list)
        {
            postProcess(item);
        }

        return list;
    }
}

或者使用界面,这样您就不必通过操作:(我更喜欢这个)

public interface IDo
{ 
    Do();
}

public static class Foo
{
    public static IList<T> Bar(this DataTable table) where T : IDo
    {
        IList<T> list = ... // do something with DataTable.

        foreach(T item in list)
        {
            item.Do();
        }

        return list;
    }
}

答案 4 :(得分:1)

你可以做任何一次

public static IList<T> Bar<T>(this DataTable table, Action<T> postProcess)
{
   ...
   postProcess(someT);
   ...
}

或添加通用约束:

public static IList<T> Bar<T>(this DataTable table)
   where T : IHasPostProcess
{
   ...
   someT.postProcess();
   ...
}