这可能是不可能的,但我希望它是!
我有一个方法,它具有泛型类型的范围,并且实现了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}},因此我无法互换它们。有什么建议或者这不可能吗?
答案 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。