2011-03-17 53 views
3

我有以下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都可以为空。

+0

Eric Lippert解释了为什么在LINQ中没有内置的方法来实现它:http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx – 2011-03-17 12:57:19

回答

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

编辑: 从您的编辑,现在看来,你并不需要一个不同的类型来表示投影数据,因为“合并”属性仍意味着是空。如果你不想改变现有的集合,并且你不喜欢你当前的查询,那么你最好的选择仍然是在源类型中编写一个转换方法。

+0

谢谢。我有你的想法。我编辑了我的答案,即“source”和“source2”具有相同的结构100%。 'ParentId'的值唯一不同。 – Homam 2011-03-17 12:27:01