【问题标题】:Calling a Delegate of an instance method on a Generic在泛型上调用实例方法的委托
【发布时间】:2011-03-25 14:14:42
【问题描述】:

我没有太多运气来寻找这个答案,因为我认为我对它的正确术语了解不够。

(为了清晰的代码和我如何称呼它而编辑)

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

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 挑战。

或者,也许这根本不可能?

【问题讨论】:

  • 您的第一个示例也不起作用,是吗?无法从DataTable 推断出T
  • Bar 也没有定义为泛型,T 也没有在其他任何地方定义(当然,假设没有名为 T 的实际类型)
  • 我大大减少了我实际拥有的代码,并且无意中遗漏了一些东西,因为我急于发布这个问题以得到一些工作。第一个示例确实适用于我的世界...我会看看是否可以对其进行编辑以使其更有意义。
  • 亨克和亚当,我才意识到你在指出什么。现在正在针对这一点进行编辑...

标签: c# .net linq generics delegates


【解决方案1】:

你想要的是一个Action,这样你就可以做到:

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;
    }
}

【讨论】:

  • T 是 IList 中项目的通用类型。我没有正确理解你吗?
  • 列表为返回类型。见亚当的回答。
【解决方案2】:

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

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

所以,

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;
}

【讨论】:

    【解决方案3】:

    签名是

    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);
    

    【讨论】:

    • 我接受了这个,因为根据 stackoverflow,它在技术上是第一个,并且还提供了一个示例来调用它。这正是我想要的。
    【解决方案4】:

    你可以做任何一个

    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();
       ...
    }
    

    【讨论】:

    • 我想你的意思是T : IHasPostProcess
    【解决方案5】:

    试试Action&lt;T&gt;:

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多