繁体   English   中英

添加为可变类型,就好像它是不可变的(无序)

[英]Adding to a mutable type as if it was immutable (orderlessly)

我在窗体上建立一个对象:

return table.Rows.Cast<DataRow>()
  .Select(row => new Something
  {
    Field = row["field1"] as int?,
    Bunch = GetBunch(index)
  });

使用GetBunch()如下。

private IList GetBunch(int index) { ... }

它按预期工作。 现在,我们注意到我们需要向放入Bunch的数组中添加一个附加元素。 由于多种原因,更改方法的签名不是一种选择,也不可以在其中添加额外的元素。

我试图像这样添加额外的东西:

return table.Rows.Cast<DataRow>()
  .Select(row => new Something
  {
    Field = row["field1"] as int?,
    Bunch = GetBunch(index).Add(new Thingy() { ... })
  });

但是它没有用,因为Add()不会返回包含新元素的原始数组。 它返回一个int 如果原始对象是不可变的,则Add()的结果将是我希望的,但是显然不是。

是否可以使可变对象不变? 如果不是(因为我确定不是),我如何轻松处理? (轻松地=无需存储创建的东西,然后访问它并将元素添加到Bunch属性的数组中。)

注意,在这种情况下,结果的顺序并不重要。 合适的类型应该是某种类型的Bag ,但我受现有设计的束缚。

可能是这样的:

return table.Rows.Cast<DataRow>()
.Select(row => {
                  var list = GetBunch(index);
                  list.Add(new Thingy() { ... });
                  return new SomeThing 
                         {
                            Field = row["field1"] as int?,
                            Bunch = list
                         };
                });

正如@Chris在评论中指出的那样,您可以使用lambda语句,您不一定需要使用lamda表达式。您可以在块内执行任何您想执行的操作,因为它只是一个采用DataRow并返回SomeThing

好的Selman22答案的替代方法:创建帮助程序扩展方法,该方法可以让您添加到GetBunch()结果中,而无需将其包装在lambda内联中:

static class MyListExtenstions
{
  static IList AddToList<T>(this IList list, T item)
  {
    list.Add(item);
    return list;
  }
}

并内联使用:

return table.Rows.Cast<DataRow>()
  .Select(row => new Something
     {
         Field = row["field1"] as int?,
         Bunch = GetBunch(index).AddToList(new Thingy() { ... })
     });

另一种LINQ方法可以创建更多的中间对象,但可以在不可变(意味着添加项目会引发异常)列表上工作:

如果要使用可用于链接的方法,则可以使用IEnumerable<T>.Concat() (在您的情况下,可以使用.ToList() )。 这种方法将为您提供新的列表,如果GetBunch结果为:

 GetBunch(index)
    .Concat(Enumerable.Repeat(new Thingy() { ... }, 1))
    .ToList()

注意:如果您的GetBunch返回通用IList<T>IEnumerable<T> ,则可以使用Enumerable辅助方法(如.Concat() )。 由于它返回非通用版本,因此您需要使用Enumerable.Cast东西将其转换为通用变体,或转换为通用接口以使用LINQ方法。 您需要知道实际的类型是什么,或者应该返回什么类型的项目。

 GetBunch(index).Cast<object>()
 GetBunch(index) as IList<Thingy> 
return table.Rows.Cast<DataRow>()
    .Select(row => new Something
    {
        Field = row["field1"] as int?,
        Bunch = GetBunch(index).Union(x => 
            new[] { new Thingy() { ... } }
            ).ToList()
    });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM