Вызов делегата метода экземпляра на универсальном - PullRequest
2 голосов
/ 25 марта 2011

Мне не очень повезло в поисках этого ответа, так как я думаю, что не знаю достаточно о правильных терминах для него.

(Изменить для ясности кода и как я его называю)

У меня есть класс, который создает метод расширения:

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 ... делегат, предикат или действие, главным образом потому, что я по-прежнему вызываю Линка.

Или, может быть, это даже невозможно?

Ответы [ 5 ]

3 голосов
/ 25 марта 2011

То, что вы хотите, это действие , так что вы можете сделать:

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;
    }
}
2 голосов
/ 25 марта 2011

Во-первых, вам нужно определить 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;
}
1 голос
/ 25 марта 2011

Вы можете сделать либо

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();
   ...
}
1 голос
/ 25 марта 2011

Попробуйте 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;
    }
}
1 голос
/ 25 марта 2011

Сигнатура будет

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 переносит практически все сигнатуры методов в таблицу, которые могут вам понадобиться через Action и Func делегатов.В то время как action охватывает все методы с возвращаемым типом void, Func вводит не пустые возвраты.

Обратите внимание, что 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...