我是程序员,我很懒。目前我正在使用C#中的一些OpenAL包装器。每次调用OpenAL方法时,我都必须使用GetError
从OpenAL请求错误,如果有,我抛出异常。在我添加一个包含以下函数的静态助手类之前,它没用多久:
public static void Check()
{
ALError error;
if ((error = AL.GetError()) != ALError.NoError)
throw new InvalidOperationException(AL.GetErrorString(error));
}
这工作了一段时间,但我想要更多。所以,过了一会儿,我提出了以下方法:
public static void Call(Action function)
{
function();
ALHelper.Check();
}
public static void Call<TParameter>(Action<TParameter> function, TParameter parameter)
{
function(parameter);
ALHelper.Check();
}
public static TReturn Eval<TReturn>(Func<TReturn> function)
{
var val = function();
ALHelper.Check();
return val;
}
public static TReturn Eval<TParameter, TReturn>(Func<TParameter, TReturn> function, TParameter parameter)
{
var val = function(parameter);
ALHelper.Check();
return val;
}
这很好用,但我仍然不满意代码在使用时的外观,所以我决定更进一步:我将上述方法转换为扩展方法。据我所知,我可以将方法作为Action
和Func
参数传递,我认为它对扩展方法也有效,将丑陋的handles = ALHelper.Eval(AL.GenBuffers, amount)
变为更优雅的handles = AL.GenBuffers.Eval(amount)
可悲的是,一旦我开始使用它,我就受到了例外的欢迎:表达式表示method group', where a
变量&#39;,value' or
类型&#39;是预期的。
有点难过,这不起作用,我真的很好奇为什么这不起作用。您可以将方法作为Action
或Func
传递的原因究竟是什么,但使用扩展方法并不起作用?这是我使用的Mono编译器的限制(.NET 4.0)我正在使用,或者内部还有其他内容?
答案 0 :(得分:2)
我认为你误解了扩展方法的概念。它们用于扩展类型。在这种情况下,AL.GenBuffers
是一种方法,它不是Func
或Action.
它的签名可能与它们兼容但它并不意味着它是一个功能或动作或任何其他代表类型。在您的示例中,由于method group conversions,您可以像AL.GenBuffers
一样传递它。当编译器看到方法签名兼容时,它会将其转换为delegate
类型。
答案 1 :(得分:1)
当您编写handles = ALHelper.Eval(AL.GenBuffers, amount)
时,AL.GenBuffers
不是任何类型的委托。重载决策会考虑ALHelper.Eval
的所有重载,并找到一个可以转换表达式AL.GenBuffers
的委托类型。
当您编写handles = AL.GenBuffers.Eval(amount)
时,AL.GenBuffers
仍然不是任何类型的委托,因此AL.GenBuffers.Eval
与任何方法都不匹配,并且重载解析无法帮助找到最佳匹配。
您可以编写new Func<T, TResult>(AL.GenBuffers).Eval(...)
,原则上,扩展方法可以对委托类型起作用,但这比您已经拥有的更糟糕。
这不是Mono特有的。
我要做的是创建一个类(比如说MyAL
),并为所有AL
的函数提供包装器。然后,来电者可以说handles = MyAL.GenBuffers(amount);
。