我尝试实现一个装饰器模式来处理数据库事务中的错误。我对标准Func和Actions没有任何问题,但是我对使用 out 参数的函数有困难。
这里有许多相同问题的主题,我想出来实现我自己的委托:
public delegate TResult FuncWithOut<T1, T2, TResult>(T1 arg1, out T2 arg2);
1)但我还没有找到如何基于此委托实现方法:
private void SafetyExecuteMethod(Action action)
{
try
{
action();
}
catch (Exception ex)
{
// Some handling
}
}
private T SafetyExecuteFunction<T>(Func<T> func)
{
T result = default(T);
SafetyExecuteMethod(() => result = func.Invoke());
return result;
}
private SafetyExecuteFunctionWithOut // ??
{
// ??
}
2)如何调用此方法:
public bool UserExists(string name)
{
return SafetyExecuteFunction(() => _innerSession.UserExists(name));
}
public void CreateUser(string name, string password)
{
SafetyExecuteMethod(() => _innerSession.CreateUser(name, password));
}
public bool CanUpdateUser(string userName, out string errorMessage)
{
// ??
// _innerSession.CanUpdateUser(userName, out errorMessage);
}
答案 0 :(得分:0)
使用与SafetyExecuteFunction<T>(Func<T> func)
示例中相同的方案。
您必须注意的一件事是您需要为out参数使用临时局部变量。
private TResult SafetyExecuteFunctionWithOut<T1, T2, TResult>(FuncWithOut<T1, T2, TResult> func, T1 arg1, out T2 arg2)
{
TResult result = default(TResult);
T2 arg2Result = default(T2); // Need to use a temporary local variable here
SafetyExecuteMethod(() => result = func(arg1, out arg2Result));
arg2 = arg2Result; // And then assign it to the actual parameter after calling the delegate.
return result;
}
调用该函数的工作原理如下:
public bool CanUpdateUser(string userName, out string errorMessage)
{
bool result = SafetyExecuteFunctionWithOut<string, string, bool>(_innerSession.CanUpdateUser, userName, out errorMessage);
return result;
}
请注意,您必须将_innerSession.CanUpdateUser
作为参数传递给SafetyExecuteFunctionWithOut
,而不是使用lambda表达式。
使用天真的尝试:
private TResult SafetyExecuteFunctionWithOut<T1, T2, TResult>(FuncWithOut<T1, T2, TResult> func, T1 arg1, out T2 arg2)
{
TResult result = default(TResult);
SafetyExecuteMethod(() => result = func(arg1, out arg2));
return result;
}
创建错误消息:
CS1628无法在匿名内使用ref或out参数'arg2' 方法,lambda表达式或查询表达式
为什么不允许这样做explained in this answer。