我有很多方法,一种是泛型的,另一种是非泛型的。这两种方法都将Linq表达式作为单个参数接收:
public void Test(Expression<Action<char>> expr) {}
public void Test<T>(Expression<Func<char, T>> expr) {}
现在考虑以下调用:
var sb = new StringBuilder();
Test(c => sb.Append(c));
编译器将选择通用方法,因为Append()
方法确实(不幸地)返回了StringBuilder
。但是,就我而言,我绝对需要调用非泛型方法。
以下解决方法表明代码没有类型问题(非泛型调用将完全有效):
Expression<Action<char>> expr = c => sb.Append(c);
Test(expr);
但是,我宁愿不声明具有显式类型的变量,而是以某种方式让编译器选择非泛型方法(就像我可以告诉它使用具有显式类型参数的泛型方法一样)。 / p>
您可以在SharpLab.io上玩这个游戏。
答案 0 :(得分:4)
这似乎是一种解决方法(因为是这样),但是您可以使用命名参数来阐明正在调用的方法。
static public void Test(Expression<Action<char>> action)
{
Console.WriteLine("Test()");
}
static public void Test<T>(Expression<Func<char, T>> func)
{
Console.WriteLine("Test<T>()");
}
要使用非通用版本时,只需在参数列表中提供参数名称action:
。
static public void Main()
{
var sb = new StringBuilder();
Test(action: c => sb.Append(c) );
Test(func: c => sb.Append(c) );
}
输出:
Test()
Test<T>()
与写出表达式强制转换相比,这可能更容易使用。
答案 1 :(得分:1)
您可以使用空方法吞下sb.Append的返回值。我不会将其称为解决方法,因为它只能使编译器正常工作,但也不是完全干净漂亮。
static public void NoValue(object value) {}
static public void Test(Expression<Action<char>> action)
{
Console.WriteLine("Test()");
}
static public void Test<T>(Expression<Func<char, T>> func)
{
Console.WriteLine("Test<T>()");
}
将输出包装为NoValue时,编译器正确地将其视为Action,而不是函数。
static public void Main()
{
var sb = new StringBuilder();
Test(c => NoValue(sb.Append(c)) );
Test(c => sb.Append(c) );
}
输出:
Test()
Test<T>()