如何在LINQ中更改值而不需要新的投影?

3
我有以下LINQ查询:
var source = from node in MyNods
             select new
             {
                 Id = node.Id,
                 Name = node.Name,
                 ParentId = node.ParentId, // Nullable
             };

在上面的查询中,ParentId是可为空的。现在我需要一个新的结果与第一个相匹配,但有一个小变化,如果ParentId为null,则希望它变成0
我写了以下代码:
var source2 =  from s in source
               select new
               {
                    Id = s.Id,
                    Name = s.Name,
                    ParentId = s.ParentId ?? 0, // Just change null values to 0
               };

我能用更简单的方式实现吗?(我的意思是不使用新的投影)?

编辑:新投影与第一个投影相同,两个ParentId都可为空。


Eric Lippert解释了为什么在LINQ中没有内置的方法来实现这一点:http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx - Johann Blais
1个回答

4

LINQ不适合在现有集合上执行副作用。如果您想这样做,最好采取以下方式:

foreach(var node in MyNods)
{
   if(!node.ParentId.HasValue) 
      node.ParentId = 0;
}

如果不是这种情况,你就需要进行投影。你现有的查询已经很好了;我能想到的缩短方式只有:

var source2 =  from s in source
               select new
               {
                    s.Id, s.Name,
                    ParentId = s.ParentId ?? 0
               };

编辑: 看起来您正在尝试创建一个不同的类型(即具有与源代码几乎相同的属性,但其中一个特定属性是非空的),因此您无法避免创建新类型的实例并复制属性。您可以考虑编写一个代表您想要的“真实”(非匿名)类型,并让源类型提供转换方法。然后您可以执行以下操作:

var source2 = source.Select(s => s.ToNonNullableParentVersion());

编辑: 从您的编辑中,现在看来您不需要不同类型来表示预测数据,因为“coalesced”属性仍然应该是可空的。如果您不想改变现有集合并且不喜欢当前的查询,则最好编写源类型的转换方法。


谢谢。我明白你的意思了。我编辑了我的答案,指出 sourcesource2 的结构完全相同,唯一的区别在于 ParentId 的值。 - Homam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接