是否可以组合不同类型的代理(使用返回值作为参数)?

Ale*_*rck 5 c# generics delegates

我有一个集合,我首先需要过滤,然后从中选择一个,但是如何处理集合取决于一些参数.所以我和两位代表一起去了,但不知怎的,我应该把它们结合起来:

delegate IEnumerable<T> FilterDelegate(IEnumerable<T> collection);
delegate T SelectorDelegate(IEnumerable<T> collection, ref T previous);

//Combine above two to this one:
delegate T GetItemDelegate(IEnumerable<T> collection, ref T previous);
Run Code Online (Sandbox Code Playgroud)

我试过这样的东西,但它失败了,因为委托不是匹配的类型:

static GetItemDelegate CreateDelegate(FilterDelegate filter, SelectorDelegate select)
{
    return Delegate.Combine(filter, select) as GetItemDelegate;
}
Run Code Online (Sandbox Code Playgroud)

题:

是否可以创建一个新的委托来调用第一个委托并使用返回值作为第二个的输入参数?没有ref参数我得到它与lambdas一起工作,但当然我不能使用out或者ref然后.

可编辑的例子:

namespace DelegateTest
{
   interface INumericValue
   {
       int Number { get; }
   }
   class Test : INumericValue
   {
       public Test(int i)
       {
           Number = i;
       }
       public int Number { get; }
   }
   class Program
   {
      delegate IEnumerable<T> FilterDelegate<T>(IEnumerable<T> collection) where T : class, INumericValue;
      delegate T SelectDelegate<T>(IEnumerable<T> collection, ref T previous) where T : class, INumericValue;

      delegate T CombinedDelegate<T>(IEnumerable<T> collection, ref T previous) where T : class, INumericValue;

       static void Main()
       {
           Test previous = new Test(6);
           List<Test> collection = new List<Test>();
           FilterDelegate<Test> filter = Filter;
           SelectDelegate<Test> select = Select;

           CombinedDelegate<Test> combined = Delegate.Combine(filter, select) as CombinedDelegate<Test>;

           for (int i = 0; i < 10; i++)
               collection.Add(new Test(i));

           //Expected result Test with Number = 7
           Test result = combined(collection, ref previous);
       }

       static IEnumerable<T> Filter<T>(IEnumerable<T> collection) where T : class, INumericValue
       {
          return collection.Where(c => c.Number > 3);
       }
       static T Select<T>(IEnumerable<T> collection, ref T previous) where T : class, INumericValue
       {
           var previousNumber = previous.Number;
           return previous = collection.FirstOrDefault(c => c.Number > previousNumber);
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

Evk*_*Evk 2

您可以这样做,但不确定它比链接调用干净得多:

class Program {
    delegate IEnumerable<T> FilterDelegate<T>(IEnumerable<T> collection) where T : class, INumericValue;

    delegate T SelectDelegate<T>(IEnumerable<T> collection, ref T previous) where T : class, INumericValue;

    delegate T CombinedDelegate<T>(IEnumerable<T> collection, ref T previous) where T : class, INumericValue;

    static void Main() {
        Test previous = new Test(6);
        List<Test> collection = new List<Test>();
        FilterDelegate<Test> filter = Filter;
        SelectDelegate<Test> select = Select;
        for (int i = 0; i < 10; i++)
            collection.Add(new Test(i));
        // use explicit types to be able to use ref in lambda
        CombinedDelegate<Test> combined = (IEnumerable<Test> c, ref Test p) => @select(filter(c), ref p);
        Test result = combined(collection, ref previous);
        //Expected result Test with Number = 7
    }

    static IEnumerable<T> Filter<T>(IEnumerable<T> collection) where T : class, INumericValue {
        return collection.Where(c => c.Number > 3);
    }

    static T Select<T>(IEnumerable<T> collection, ref T previous) where T : class, INumericValue {
        // this didn't compile so I changed it.
        foreach (var item in collection) {
            if (item.Number > previous.Number) {
                previous = item;
                break;
            }
        }
        return previous;
    }
}
Run Code Online (Sandbox Code Playgroud)