4

是否可以使用 TPLTask<TResult>异步调用具有以下签名的线程安全方法并检索布尔返回值和输出参数?

public bool TryGet(T1 criteria,
                   out T2 output)

显然,由于输出参数,我不能使用 lambda 表达式。此外,我无法通过定义如下所示的自定义委托并将其传递给Task<TResult>构造函数来解决问题,因为我需要将标准作为构造函数不支持的强类型参数传递。

public delegate TResult Func<T1, T2, TResult>(T1 arg1,
                                              out T2 arg2);

编写如下包装器并异步调用它的最佳选择是什么?

public Tuple<bool, T2> TryGetWrapper(T1 criteria)
{
    T2 output;

    bool result = obj.TryGet(criteria,
                             out output);

    return new Tuple<bool, T2>(result,
                               output);
}

只是看起来有点不雅,而且有一点点味道。

4

2 回答 2

4

这也是我纠结过的事情。

我想出了一个类似的解决方案,除了使用 Tuple 之外,我编写了一个简单的包装类,只是为了让事情更具可读性。

我也有兴趣看到任何更好的解决方案——但你提出的建议似乎和我想出的任何东西一样好。

这是我的包装类及其用法的样子。这不是您问题的答案;只是一个建议(也许)使您的解决方案更具可读性。

(尽管我承认Task<TryResult<DateTime>>声明本身可能不被认为是可读的!)

using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    internal class Program
    {
        static void Main()
        {
            string dateString = "Invalid Date";

            var tryParseDateTask = new Task<TryResult<DateTime>>(() =>
            {
                DateTime result;

                if (DateTime.TryParse(dateString, out result))
                    return TryResult<DateTime>.Success(result);
                else
                    return TryResult<DateTime>.Failure();
            });

            tryParseDateTask.Start();

            if (tryParseDateTask.Result.IsSuccessful)
                Console.WriteLine(dateString + " was parsed OK.");
            else
                Console.WriteLine(dateString + " was parsed as " + tryParseDateTask.Result.Value);
        }
    }

    public class TryResult<T>
    {
        public static TryResult<T> Success(T value)
        {
            return new TryResult<T>(value, true);
        }

        public static TryResult<T> Failure()
        {
            return new TryResult<T>(default(T), false);
        }

        TryResult(T value, bool isSuccessful)
        {
            this.value = value;
            this.isSuccessful = isSuccessful;
        }

        public T Value
        {
            get
            {
                return value;
            }
        }

        public bool IsSuccessful
        {
            get
            {
                return isSuccessful;
            }
        }

        readonly T value;
        readonly bool isSuccessful;
    }
}
于 2013-04-29T10:29:00.667 回答
1

我认为你的方法几乎是你能做的最好的。如果您经常这样做,您可以使用辅助方法将带out参数的委托转换为Tuple-returning 委托(或类似TryResult-returning,如 Matthew Watson 的回答):

public delegate TResult OutFunc<TIn, TOut, TResult>(TIn input, out TOut output);

public static Func<TIn, Tuple<TResult, TOut>> OutToTuple<TIn, TOut, TResult>(
    OutFunc<TIn, TOut, TResult> outFunc)
{
    return input =>
    {
        TOut output;
        TResult result = outFunc(input, out output);
        return Tuple.Create(result, output);
    };
}
于 2013-04-29T13:27:28.057 回答