2017-08-15 51 views
0

我想將兩個IList合併成一個,其中之一或兩者都可以是null。如果兩者都是null我希望結果爲null安全地結合兩個IList,佔空位

我有這個,但我想要更優雅的東西,但仍然容易閱讀。

private IList<Filter> CombineFilters(IList<Filter> first, IList<Filter> second) 
{ 
    IList<Filter> result = null; 

    if(first != null) 
     if (second != null) 
      result = first.Concat(second) as IList<Filter>; 
     else 
      result = first; 
    else if (second != null) 
     result = second; 

    return result; 
} 
+1

可能會更好地詢問代碼審查,因爲它似乎是工作代碼。我可能會問,爲什麼你試圖避免將'null'分配給'result',如果事實證明這是正確的結果(即爲什麼'else if')? –

+1

你需要'first.Concat(second).ToList()'而不是'as IList '否則結果將爲空 –

+0

@Damien_The_Unbeliever'else if'發生在'first'爲'null'和'second '不是 – Bobbler

回答

3

我會認爲這是一個有點怪異的行爲,如果我打電話給你CombineFilters有兩個列表(一個可能爲空),並得到一個列表,它是不是副本。這將導致以下行爲:

List<Filter> filters1 = new List<Filter>() { new Filter() }; 
List<Filter> filters2 = null; 

Console.WriteLine(filters1.Count); // 1 

var filters = CombineFilters(filters1, filters2); 
filters.Add(new Filter()); 

Console.WriteLine(filters.Count); // 2 
Console.WriteLine(filters1.Count); // also 2 

我不確定我是否真的期待這種行爲。

所以我建議你總是保證最後會有一個新的列表。這可以讓你做這個真的很短:

private IList<Filter> CombineFilters(IList<Filter> first, IList<Filter> second) 
{ 
    return (first ?? Array.Empty<Filter>()).Concat(second ?? Array.Empty<Filter>()).ToList(); 
} 
+0

感謝您的優雅的答案。爲什麼要更好地列出新列表?我更願意只在必要時實例化。 – Bobbler

+1

這不一定更好,但它會帶來更一致的體驗。由於該方法返回一個'IList'我希望被允許修改它;但修改應該不會影響我的原始列表。如果你要返回一個'IEnumerable',那麼你可以避免這種情況,因爲這是不可設計的。 – poke

1
private IList<Filter> CombineFilters(IList<Filter> first, IList<Filter> second) 
{ 
    if (first == null && second == null) return null; 
    first = first ?? new List<Filter>(); 
    second = second ?? new List<Filter>(); 
    return first.Concat(second).ToList(); 
} 
+0

'Enumerable.Empty ()'怎麼樣? – haim770

+0

我錯過了那一點。看起來有點奇怪,有一個函數,其輸入中的合約爲空 - 爲空,但可能返回null。 – Puppy

3

使用Enumerable.Concate??運營商一起:

if(first == null && second == null) 
    return null; 
return Enumerable.Concat(first ?? Enumerable.Empty<IFilter>(), 
         second ?? Enumerable.Empty<IFilter>()).ToList(); 

如果任firstsecondnull一個新的列表將被用來代替的CONCAT。


我認爲,在這兩種情況下,列表是null那麼仍然應該返回一個初始化集合。在這種情況下,只需刪除if語句。也可能返回IEnumerable而不是IList

private IEnumerable<Filter> CombineFilters(IEnumerable<Filter> first, IEnumerable<Filter> second) 
{ 
    return Enumerable.Concat(first ?? Enumerable.Empty<IFilter>(), 
          second ?? Enumerable.Empty<IFilter>()); 
} 

返還IEnumerable而不是IList取決於您的方案。在這裏閱讀更多:

1

你可以做這樣的事情:

private IList<Filter> CombineFilters(IList<Filter> first, IList<Filter> second) 
{ 

    if (first == null && second == null) 
    { 
     return null; 
    } 

    return (first ?? Enumerable.Empty<Filter>()) 
      .Concat(second ?? Enumerable.Empty<Filter>()) 
      .ToList(); 
} 

這就是說,它是一個很好的做法,以避免完全空的集合;如果沒有元素,則只返回一個空集合。這樣,你不需要一直檢查空值。這可能不適合你的情況,但如果是這樣,它會使你的代碼更清潔一些。

而且,考慮使用IEnumerable<T>而不是IList<T>,因爲它是一個更一般的抽象(也因爲IList<T>是一個壞了,漏水的抽象 - 實現拋出他們不支持的方法異常()!)。另一方面,我可以看到這是一種私人方法,如果您實際上始終通過List<Filter>,則最好將參數聲明爲List<Filter>

編輯:
只是注意到我的答案非常類似於Gilad Green發佈的one,我之前沒有看到。

+0

'IList '如何泄漏? – Bobbler

+0

@Bobbler:根據它自身的優點,'IList '是可以的,但是,在早期版本的.NET框架中,它被(或多或少)視爲一個'集合'概念的抽象。因此,.NET 2.0中的很多集合都實現了IList ,儘管其中許多集合都不支持該接口定義的方法的重要子集。他們的解決方案是拋出'NotSupportedException',這非常可怕。這違反了Liskov原理,並減少了IList '的用處。然後他們認爲這些集合是你可以枚舉的東西('IEnumerable ')。 –