在LINQ中如何在没有新投影的情况下更改值?

时间:2011-03-17 12:05:05

标签: c# linq

我有以下LINQ查询:

var source = from node in MyNods
             select new
             {
                 Id = node.Id,
                 Name = node.Name,
                 ParentId = node.ParentId, // Nullable
             };

在上面的查询中,ParentId可以为空。现在我需要一个与第一个匹配的新结果,但如果ParentId为空,则需要进行少量更改,我希望它为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都可以为空。

1 个答案:

答案 0 :(得分: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'属性仍然可以为空。如果您不想改变现有的集合并且不喜欢当前的查询,那么最好的选择仍然是在源类型中编写转换方法。