2013-05-10 67 views
3

我比較了兩個不同類型的枚舉,但是看到它們之間是否有任何差異。我這樣做是通過鑄造他們既兼容匿名類型的可枚舉列表:使用LINQ比較兩個序列的差異

var curCombo = (from c in curPlan.TPM_TRAININGPLANSOLUTIONS orderby c.TASKID select new { Id = c.TASKID, Marker = c.ISMARKERCOMPLETION }); 
var newCombo = (from c in plan.Combo orderby c.TaskId select new { Id = c.TaskId, Marker = c.Marker }); 

然後看看如果序列是一樣的:

bool equals = curCombo.SequenceEqual(newCombo); 

這工作得很好,但是如果plan.Combo爲null,我得到一個異常。不幸的是,我不能強制這個數組永遠不能爲空。實際上似乎沒有辦法將newCombo設置爲空的陣列,並仍然將兩者與SequenceEqual進行比較,並且將整個事件設置爲if塊來捕獲該條件似乎相當混亂。我想要一個單一的,雄辯的LINQ語句。

有一兩件事我想會是這樣的:

var newCombo = (from c in plan.Combo ?? new TrainingPlanCombo[0] orderby c.TaskId select new { Id = c.TaskId, Marker = c.Marker }); 

然而,這似乎有點哈克。想法?

+0

問題是'plan.Combo'是空集合的空insteaf,這是最佳實踐。 – 2013-05-10 22:34:55

+0

@TimSchmelter - 同意。但是'plan.Combo'從一些來自Web瀏覽器的JSON反序列化,所以很難執行。 – 2013-05-10 22:36:59

回答

3

也許你要這樣寫

public static IEnumerable<T> AssureNotNull<T>(this IEnumerable<T> list) 
{ 
    if (list == null) return Enumerable.Empty<T>(); 
    return list; 
} 

編輯的擴展方法

用法是:

List<int> nullList = null; 
var sum = nullList.AssureNotNull().Sum(); //will be 0 
+0

我其實挺喜歡這個解決方案。我*可以*覆蓋'.Combo'上的getter來返回一個空數組,但是我真的不喜歡*假設的代碼*某些東西永遠不會爲空。 – 2013-05-10 22:46:07

+1

+1 @MikeChristensen:你不需要改變getter,你只需要用這個擴展名修改查詢'... plan.Combo.AssureNotNull()...' – 2013-05-10 22:47:42

+0

@TimSchmelter - 是的,我說的是我*更喜歡*這個解決方案*改變我的getter,因爲它使代碼更加防彈。 – 2013-05-10 22:56:33

0

您可以使用monads在.NET來實現你想要:

var newCombo = plan.With(p=>p.Combo.OrderBy(c=>c.TaskId) 
            .Select(c=>new { Id = c.TaskId, Marker = c.Marker })); 

bool equals = newCombo.Returns(n=>n.SequenceEqual(curCombo), false);