1

在这篇文章中,通过用出纳员替换查找器 来避免空值检查,作者给出了一个 Ruby 示例来避免空值检查,如果返回对象,则运行块,如果没有,则不运行。

 data_source.person(id) do |person|
  person.phone_number = phone_number
  data_source.update_person person
end

我想在 C# 中使用 lambda 函数做同样的事情,但在想出一个做同样类型事情的例子时遇到了麻烦。你会创建对象工厂来接受 id 号和 lambda 函数吗?

4

2 回答 2

5

好吧,我不了解 Ruby,也不理解给出的确切示例,但我怀疑它会是这样的:

dataSource.Update(id, person => person.PhoneNumber = phoneNumber);

哪里DataSource.Update会:

  • 有类似的签名void Update(string id, Action<Person> updateAction(或者可能返回一个bool以表明它是否找到了这个人)
  • 实现为:
    • 查找具有给定 ID 的人
    • 如果不存在,立即返回
    • 否则,执行给定的操作,并使用修改后的对象更新后备存储

或者更一般地说(更接近原始 Ruby):

dataSource.WithPerson(id, person => {
    person.PhoneNumber = phoneNumber;
    dataSource.UpdatePerson(person);
};

就我个人而言,我更喜欢第一种形式:它更具体地说明了它试图实现的目标,但这很可能有助于更好的实现,而且它在调用代码中肯定更干净。

于 2013-07-03T16:14:30.557 回答
2

另一种方法是使用Maybe monad

这将允许您保持现有 API 不变,即您仍然可以拥有一个dataSource.GetPersonById(id).

使用 Maybe monad 的代码如下所示:

dataSource.GetPersonById(id)
          .Maybe()
          .Do(person => {
                            person.PhoneNumber = phoneNumber;
                            dataSource.UpdatePerson(person);
                        });

为了能够使用 Maybe monad,您需要拥有以下段落中的代码。
它的基础是 Daniel Earwicker 的链接博客文章中的代码。
我对其进行了扩展以添加Maybe扩展方法并使其编译。

public struct MaybeMonad<T> where T : class
{
    private readonly T _value;

    public MaybeMonad(T value)
    {
        _value = value;
    }

    public MaybeMonad<TResult> Select<TResult>(Func<T, TResult> getter)
        where TResult : class
    {
        var result = (_value == null) ? null : getter(_value);
        return new MaybeMonad<TResult>(result);
    }  

    public TResult Select<TResult>(Func<T, TResult> getter,
                                   TResult alternative)
    {
        return (_value == null) ? alternative : getter(_value);
    }

    public void Do(Action<T> action)
    {
        if (_value != null)
            action(_value);
    }
}

public static class Maybe
{
    public static MaybeMonad<T> From<T>(T value) where T : class
    {
        return new MaybeMonad<T>(value);
    }
}

public static class MaybeMonadExtensions
{
    public static MaybeMonad<T> Maybe<T>(this T value) where T : class
    {
        return new MaybeMonad<T>(value);
    }
}
于 2013-07-03T16:45:29.930 回答