添加到一个可变类型,好像它是不可变的(无序)

时间:2014-09-04 14:04:56

标签: c# arrays immutability

我正在表单上构建一个对象:

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 ,但我已经被现有的设计所束缚。

3 个答案:

答案 0 :(得分:5)

这样的事情可能是:

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表达式。你可以在块内做任何你想做的事情,因为它只是一个需要{{1}的方法并返回DataRow

答案 1 :(得分:2)

替代好的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> 

答案 2 :(得分:0)

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