【问题标题】:Implement calling delegate with out parameters实现无参数调用委托
【发布时间】:2018-10-03 05:48:46
【问题描述】:

我尝试实现一个装饰器模式来处理数据库事务中的错误。我对标准的 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);
    }

【问题讨论】:

  • 1) 究竟是什么问题?它编译吗?还有什么? 2) 三种方法。哪个?
  • 1) 我不知道如何实现“SafetyExecuteFunctionWithOut”方法。 2)以及如何调用这个方法

标签: c# delegates decorator out


【解决方案1】:

只需使用与SafetyExecuteFunction&lt;T&gt;(Func&lt;T&gt; 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

【讨论】:

  • 非常感谢,非常有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多