c# - TryParse困境-处理out参数

标签 c# functional-programming out

<分区>

我从来不喜欢 outref 参数。当我看到它们在运行时,它们给我一种设计有些困惑的感觉。

我认为唯一的异常(exception)是所谓的 TryXXX 模式,它返回一个 bool 值作为函数结果(无论是一切正常还是出现问题)和一个实际结果的输出参数,直到我读到 this article今天,它让我思考是否有更好的模式来实现这种方法。

我认为我们可以有一个返回多个结果的函数(或者如文章所说的元组)

Tuple<Exception,T> TryParseT(object obj)

或接受成功回调函数的函数:

void TryParseT(object obj,Action<T> success)

问题是,从功能设计的角度来看,哪个更好?

更新: 换句话说,我想知道这两个函数中哪个更符合函数式编程原则,为什么?

最佳答案

最优雅的方法是

int Parse(string value)

Tryxxxx 方法仅针对名为性能的实现细节而存在。如果您正在寻求优雅,您可以使用 Parse 方法并通过快速失败来处理任何错误。 您可以改为返回一个元组,但这将在堆上花费额外的分配,因为元组是引用类型。

在性能方面(如果您关心的话)更好的解决方案是键值对。但它隐藏了(如元组)通用数据类型背后的语义,这对于代码清晰度来说并不是最佳选择。与定义元组的第一个 bool 包含失败状态的某种约定相比,发出失败信号的更好方法是定义您自己的数据类型。

struct ParseResult<T>
{
    public bool Success { get; private set; }
    public T Value { get; private set; }

    public ParseResult(T value, bool success):this()
    {
        Value = value;
        Success = success;
    }
}

class Program
{
    static ParseResult<int> TryParse(string s)
    {
        int lret = 0;
        if (int.TryParse(s, out lret))
        {
            return new ParseResult<int>(lret, true);
        }
        else
        {
            return new ParseResult<int>(lret, false);
        }

    }

    static void Main(string[] args)
    {

        string test = "1";
        var lret = TryParse(test);
        if( lret.Success )
        {
            Console.WriteLine("{0}", lret.Value);
        }
    }
}

该方法仍然非常有效,并且以分配廉价容器对象为代价节省了 out 参数。

关于c# - TryParse困境-处理out参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30555045/

相关文章:

scala - 如何在抽象效果类型上配置猫计时器

c++ - 使用使用 C 样式字符串作为 OUT 参数的 WinAPI 函数

c# - 可空列表 <> 作为输出参数

android - 淡出 TextView 的最后几行

c# - 为什么代码中定义的 Storyboard不起作用?

c# - 如何获得SecondOrDefault?

clojure - 如何以纯函数的方式实现观察者设计模式?

c# - 在 IIS 中禁用 Windows 授权的情况下获取 Windows 用户凭据

c# - C# 中的 MySQL 查询命令 SELECT 不返回任何内容

functional-programming - ML 函数柯里化(Currying)