如何在不知道T的范围的情况下传递Func <t> </t>

时间:2013-01-14 10:38:46

标签: c# generics

这可能是不可能的,但我希望它是!

我有一个方法,它具有泛型类型的范围,并且实现了List<Func<GenericType>>。然后我有另一种方法收到List<Func<T>>。我不能在这种方法中了解T

示例代码

public void PassFuncs<Item>()
{
  List<Func<Item>> funcs = new List<Func<Item>>();
  RecieveFuncs(funcs);
}
public void RecieveFuncs(List<Func<object>> funcs)
{
  //Do some stuff with funcs
}

我希望用object取代T就像使用T一样容易,而且就这么简单。当然,object不是Type,而是{{1}},因此我无法互换它们。有什么建议或者这不可能吗?

4 个答案:

答案 0 :(得分:4)

您可以将方法设为通用:

public void RecieveFuncs<T>(List<Func<T>> funcs)
{
  //Do some stuff with funcs
}

要调用它,您可以明确声明T

public void PassFuncs<Item>()
{
  List<Func<Item>> funcs = new List<Func<Item>>();
  RecieveFuncs<Item>(funcs);
}

或让类型推理魔术完成它的工作并按原样保持呼叫:

public void PassFuncs<Item>()
{
  List<Func<Item>> funcs = new List<Func<Item>>();
  RecieveFuncs(funcs);  // C# automatically infers T = Item
}

答案 1 :(得分:3)

如果你知道Item是一个引用类型,你可以使用每个函数的方差(但不是列表的方差):

public void PassFuncs<Item>() where Item : class
{
    List<Func<Item>> funcs = new List<Func<Item>>();
    var tmp = funcs.ConvertAll(func => (Func<object>)func);
    RecieveFuncs(tmp);
}

这会创建一个新列表,但会使用原始函数。如果无法做到这一点,您需要添加一个中间函数:

public void PassFuncs<Item>()
{
    List<Func<Item>> funcs = new List<Func<Item>>();
    var tmp = funcs.ConvertAll<Func<object>>(func => () => func());
    RecieveFuncs(tmp);
}

答案 2 :(得分:3)

如果由于某种原因无法使RecieveFuncs通用,您可以使用:

public void PassFuncs<TItem>()
    where TItem:class
{
  List<Func<TItem>> funcs = new List<Func<TItem>>();
  RecieveFuncs(funcs);
}

public void RecieveFuncs(IEnumerable<Func<object>> funcs)
{
  //Do some stuff with funcs
}

这需要通用约束来引用TItem的类型,并且需要在接收方使用IEnumerable<T>而不是List<T>的共变体接口。如果您确实想要收到List<Func<object>>,可以使用List<Func<object>>(funcs)创建新列表。

答案 3 :(得分:0)

您可以将Func<Item>“投射”到Func<object>,就像这样

public delegate object Func();

public void PassFuncs<Item>()
{
  List<Func<Item>> funcs = new List<Func<Item>>();
  RecieveFuncs(funcs.Select<Func<Item>, Func<object>>(f => () => (object)f())
                    .ToList());
}

public void RecieveFuncs(List<Func<object>> funcs)
{
  //Do some stuff with funcs
}

这对参考和值类型都有效,尽管它会为值类型添加框。如果仅使用引用类型,请使用@CodesInChaos answer。