2013-07-03 76 views
1

在本文中Avoid Null Checks by replacing finders with tellers 作者給出了一個Ruby示例以避免空檢查,如果對象返回該塊運行,如果不是,那麼它不是。避免使用lambdas進行空值檢查

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

我想用一個lambda函數做同樣的事情在C#但我有想出做同樣類型的事情爲例麻煩。你會創建對象工廠來接受id號和lambda函數嗎?

回答

5

好吧,我不知道Ruby和不瞭解確切的例子給出的,但我嫌疑它會是這樣的:

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

其中DataSource.Update會:

  • 有一個類似void Update(string id, Action<Person> updateAction(或可能返回bool來表示是否找到該人)的簽名
  • 被實現爲:
    • 查找具有給定ID的人
    • 如果它不存在,與修改後的對象
立即返回
  • 否則,執行給定的動作,並更新後備存儲

    或更一般的(並且更接近原始紅寶石):

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

    我個人公關第一種形式:更具體的是它試圖達到什麼目的,但這可能更適合於更好的實現,並且在調用代碼中它當然更清晰。

  • 2

    另一種方法是使用Maybe monad

    這將允許您保持原有的API,即您仍然可以擁有dataSource.GetPersonById(id)。使用了也許單子

    代碼如下所示:

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

    爲了能夠使用也許單子,你就必須下段的代碼。
    它的基礎是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); 
        } 
    }