2016-09-07 78 views
1

我經常在我們的項目中遇到諸如「序列包含多個元素」等非信息性消息。它偶爾會發生。.Single(),.SingleOrDefault()方法的實際用法

是不是更好地檢查:

var count = collection.Count(i => predicate); 
if (count > 1) 
{ 
    throw new InformativeException("..."); 
} 

if (count == 0) 
{ 
    throw new AnotherInformativeException("..."); 
} 

我真的不明白在什麼情況下Single()/ SingleOrDefault()可能會有用。只有當你將捕獲InvalidOperationException並嘗試將其轉換爲更多的信息。

+1

當只有最多隻有一個匹配值時,單一是理想的,例如,檢查唯一標識符 - 如果列表中有兩個值具有相同的「唯一」標識符,那麼事情就會被打破,我希望Single會拋出並告訴我。 – stuartd

+0

有關Single()等的概述,您可以查看['LINQ'文檔](http://stackoverflow.com/documentation/c%23/68/linq-queries/329/first- firstordefault-last-lastordefault-single-and-singleordefault#t = 201609071055283913178) – Nico

回答

0

SingleSingleOrDefault應當在您期望唯一的一個或一個或分別沒有時使用。

你可以通過明確檢查計數的方式來做到這一點(這是傳統的方法),但有時代碼可以更簡潔和/或更容易遵循,當你讓LINQ拋出異常你:

try { 

    // a bunch of stuff 

    var x = y.Where(z => z.ID = id).Single(); 

    // more stuff 

} catch (SomeException e) { 
    // other expected issue 
} catch (OtherException e) { 
    // other expected issue 
} catch (InvalidOperationException e) { 
    // how'd we wind up with more (or less) than 1??? 
} catch (Exception e) { 
    // unexpected issue 
} 

一些(包括我自己)可能更傾向於有外圍的驗證代碼(這基本上是上面有哪些代表)出的主要邏輯塊的方式。請注意,這並不能忽視主要的邏輯要求,因爲Single()明確告訴我們我們期望一個且只有一個項目,因此通過將計數驗證移至異常處理程序不會導致知識丟失。

我的確希望它拋出一個比InvalidOperationException更具體的異常,雖然......這是非常通用的。

1

單和的SingleOrDefault()可以在下列scenrarios使用:

  • Single()期望的單個元件,以在正在使用的匹配序列被發現。 如果序列爲空或包含多個元素,它會引發一個期望。

  • SingleOrDefault()當匹配序列爲空不拋出異常(和返回detault,通常null),但是當匹配序列包含多於一個的元件不拋出異常。

也可以使用下面的LINQ功能:

  • Count()檢查更大的值(例如> 1)

  • Any()返回true是mathicng序列中包含一個或更多的項目。

0

我用下面的方式,如果我希望只有一個元素:

try { 
    var singleElement = x.SingleOrDefault(x => /* some expression */); 
} 
catch (InvalidOperationException iopex) { 
    throw new InformativeException("More than one element found."); 
} 
if (singleElement == null) { 
    throw new InformativeException("No element found."); 
} 
// work with singleElement from here 
+1

您正在使用異常來處理無需輕鬆檢查的內容。 – Maarten

+0

確實如此,但是如果發現異常,這是代碼中的一個錯誤提示,因爲我們期望檢索零個或一個元素。因爲在正常操作過程中絕不會發生異常,所以我認爲使用異常處理是適當的。 –

2

你是對的,錯誤消息是通用的,不是很具體。但是,我認爲,他們不需要是:

有兩種情況:

  1. 這是合理可行的,有<> 1元素(例如,由於無效的配置文件條目或不太可能的用戶輸入錯誤)。在這種情況下,檢查列表中的項目數量並引發信息異常是正確的。

  2. 這是不合理的可能,有<> 1元素 - 即,如果你在這裏得到<> 1元素,你已經在別的地方編程錯誤。例如:

    // getItem's documentation guarantees that each element has a unique ID and 
    // that there is an element with ID 1. 
    var myItems = getItems(); 
    
    // if this fails, there is an implementation error in getItems 
    var item1 = myItems.Single(x => x.ID == 1); 
    

    在這種情況下,默認的錯誤信息通常就足夠了。這裏使用Single基本上是作爲運行時斷言。