如何传递函数不知道T的作用域
本文关键字:不知道 作用域 传递函数 | 更新日期: 2023-09-27 17:53:06
这可能不可能,但我希望它是!
我有一个方法,它的作用域是泛型类型,并且实例化了一个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
,因此我不能交换它们。有什么建议吗,还是这是不可能的?
你可以让你的方法泛型:
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
}
如果由于某种原因不能使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)
创建一个新的列表。
如果您知道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);
}
您可以将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答案。