开发者

Calling a Delegate of an instance method on a Generic

I'm not having much luck searching for this answer, as I think that I don't know enough about the proper terms for it.

(Edit for clarity of code and how I call it)

I have 开发者_运维问答a class that instantiates an extension method:

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

I call this method like this:

DataTable table = SomehowGetTable();

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

Again, greatly simplified.

Now, what I'd like to do, is add a delegate(?) so that after I get the list, I can call a method on each T in the list, like so:

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

I don't know what I need to be able to pass in postProcess.. a delegate, a Predicate, or an Action, mostly because I'm Linq-challenged still.

Or, maybe this isn't even possible?


What you want is an Action< T > so you can do:

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


First, you need to define Bar as generic, otherwise it won't compile.

Second, if you're trying to operate on each element within the list, you need to pass in a delegate that takes a single parameter of type T and returns no value. A built-in .NET delegate type is Action<T>, and it'll do fine.

So,

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


The signature would be

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

These days .Net brings virtually all method signatures to the table that you may ever need through Action and Func delegates. While action covers all void return type methods, Func introduces non-void returns.

Note that T must be defined as type argument on your method. The compiler may be able to infer T from the action you provide into the method:

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

For example if you are actually processing the values coming into a different type, the signature may look like :

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

Used like

List<int> values = table.Bar((double d) => (int)d);


You can do either

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

or add a generic constraint:

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


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

Or use an interface so you do not have to pass action: (I prefer this one)

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜