使用 out 参数实现调用委托
Implement calling delegate with out parameters
我尝试实现一个装饰器模式来处理数据库事务中的错误。我对标准 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);
}
只需使用与 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 Cannot use ref or out parameter 'arg2' inside an anonymous
method, lambda expression, or query expression
不允许您这样做的原因是 explained in this answer。
我尝试实现一个装饰器模式来处理数据库事务中的错误。我对标准 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);
}
只需使用与 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 Cannot use ref or out parameter 'arg2' inside an anonymous method, lambda expression, or query expression
不允许您这样做的原因是 explained in this answer。