【问题标题】:Using LINQ to compare two sequences for differences使用 LINQ 比较两个序列的差异
【发布时间】:2013-05-10 22:31:45
【问题描述】:

我正在比较两个不同类型的枚举,但看看它们之间是否有任何区别。我通过将它们都转换为兼容匿名类型的可枚举列表来做到这一点:

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 为空,我会得到一个异常。不幸的是,我不能强制这个数组永远为空。似乎没有办法将 newCombo 设置为 empty 数组,并且仍然将两者与 SequenceEqual 进行比较,并且把整个事情放在一个 if 块中来捕获它情况似乎相当混乱。我想要一个单一的、雄辩的 LINQ 语句。

我在想的一件事是这样的:

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

但是,这似乎有点 hacky。想法?

【问题讨论】:

  • 问题是plan.Combo 是空集合的空集合,这是最佳实践。
  • @TimSchmelter - 同意。但是plan.Combo 是从来自网络浏览器的一些 JSON 反序列化的,因此很难执行。

标签: c# .net linq


【解决方案1】:

也许你想写一个这样的扩展方法

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

【讨论】:

  • 我其实有点喜欢这个解决方案。我可以覆盖.Combo上的getter以返回一个空数组,但是我真的不喜欢假设某些东西永远不会为空的代码。
  • +1 @MikeChristensen:你不需要改变getter,你只需要修改带有这个扩展名的查询... plan.Combo.AssureNotNull() ...
  • @TimSchmelter - 是的,我是说我更喜欢这个解决方案而不是改变我的getter,因为它使代码更加防弹。
【解决方案2】:

你可以在.net中使用monads来实现你想要的:

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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多