【发布时间】:2018-05-18 05:51:49
【问题描述】:
在我尝试编写更多无副作用的代码(使用不可变类)时,我在使用 linq 查询数据源并选择父子关系以创建一个由不可变对象。
当我有一个子对象时问题就出现了,例如invoiceLineItem 对象需要在其构造函数中传递对父对象的引用,以便.Parent 属性将引用父对象,例如lineItem[2].Parent 引用 Invoice。
当类是不可变的时,我看不出如何使用 linq 来做到这一点。 Linq 和不可变类在 C# 中是如此重要的概念,我相信我一定遗漏了一些明显的东西。
我将展示一些演示问题的代码,首先我将展示使用不可变类似乎没有使用 Linq 的解决方案,然后在下面我将展示如何使用可变类来做到这一点,我当然会这样做不想做。
更新 : 17.05.18 我很难相信这是不可能的,因为如果是这样,那么在我看来那是语言的设计缺陷,并且该语言受到了相当严格的审查,... 更多可能我只是错过了一些东西。
我需要修复不可变类的示例( ??? ),如何在该点将引用传递给包含的类实例?
void Main()
{
var nums = new[]{
new { inv = 1, lineitems =new [] {new { qty = 1, sku = "a" }, new { qty = 2, sku = "b" }}},
new { inv = 2, lineitems =new [] { new { qty = 3, sku = "c" }, new { qty = 4, sku = "d" }}},
new { inv = 3, lineitems =new [] { new { qty = 5, sku = "e" }, new { qty = 5, sku = "f" }}}
};
// How do I pass in the reference to the newly being created Invoice
// below to the Item constructor?
var invoices = nums.Select(i =>
new Invoice(i.inv, i.lineitems.Select(l =>
new Item(l.qty, l.sku, ??? )
)));
invoices.Dump();
}
public class Invoice
{
public int Number { get; }
public IEnumerable<Item> Items { get; }
public Invoice(int number, IEnumerable<Item> items) {
Number = number;
Items = items;
}
}
public class Item
{
public Invoice Parent { get; }
public int Qty { get; }
public string SKU { get; }
public Item(int qty, string sku, Invoice parent) {
Parent = parent;
Qty = qty;
SKU = sku;
}
}
相同的类,但这次 DTO 是可变的,我们能够通过首先创建父级,然后是子级,然后通过附加现在具有对父集的引用。我需要能够使用不可变类来做到这一点,但是如何做到这一点?
void Main()
{
var nums = new[]{
new { inv = 1, lineitems =new [] {new { qty = 1, sku = "a" }, new { qty = 2, sku = "b" }}},
new { inv = 2, lineitems =new [] { new { qty = 3, sku = "c" }, new { qty = 4, sku = "d" }}},
new { inv = 3, lineitems =new [] { new { qty = 5, sku = "e" }, new { qty = 5, sku = "f" }}}
};
var invoices = nums.Select(i =>
{
var invoice = new Invoice()
{
Number = i.inv
};
var items = from item in i.lineitems select new Item()
{
Parent = invoice, Qty = item.qty, SKU = item.sku
};
invoice.Items = items;
return invoice;
});
invoices.Dump();
}
public class Invoice
{
public int Number { get; set; }
public IEnumerable<Item> Items { get; set; }
}
public class Item
{
public Invoice Parent { get; set; }
public int Qty { get; set; }
public string SKU { get; set; }
}
我希望我错过了一些明显的东西,任何帮助将不胜感激。 谢谢你 艾伦
【问题讨论】:
-
鉴于您对自己的限制,我认为没有办法做您想做的事。您有两个对象“同时”需要彼此的实例。
-
顺便说一句,您不应该将 IEnumerable 存储在这样的属性中。滥用的可能性很大。您不能确定是否可以枚举一个 ienumerable 两次。将其转换为某种只读集合。
标签: c# linq immutability