我遇到LINQ问题。我有一个项目列表,我想用以下代码将孤儿项目的Parent
值更改为0:
void Main()
{
var a = new List<Item> {
new Item() { ID = 1, Name = "1", Parent = 0 },
new Item() { ID = 2, Name = "1.1", Parent = 1 },
new Item() { ID = 3, Name = "2", Parent = 0 },
new Item() { ID = 4, Name = "3", Parent = 0 },
new Item() { ID = 5, Name = "1.2", Parent = 1 },
new Item() { ID = 6, Name = "2.1", Parent = 3 },
new Item() { ID = 7, Name = "2.2", Parent = 3 },
new Item() { ID = 8, Name = "3.1", Parent = 4 },
new Item() { ID = 9, Name = "4", Parent = 0 },
new Item() { ID = 10, Name = "5.1", Parent = 11 }
};
Test.Fix(a, x => x.ID, x => x.Parent).Dump();
}
public class Item
{
public long ID {get;set;}
public string Name {get;set;}
public long Parent {get;set;}
}
public static class Test
{
public static List<T> Fix<T>(this List<T> enumeration, Func<T, long> idProperty, Func<T, long> parentProperty)
{
enumeration = enumeration.Select(e =>
{
if (!enumeration.Any(x => idProperty(x) == parentProperty(x))) parentProperty(e) = 0;
return e;
}).ToList();
return enumeration;
}
}
我希望ID = 10
的持续项目有Parent = 0
(因为ID = 11
没有项目)但我收到错误:
The left-hand side of an assignment must be a variable, property or indexer
我用Google搜索,但仍然没有找到任何有用的信息。
任何帮助都将不胜感激!
答案 0 :(得分:2)
好的,首先这里没有动态,但正如你所说,问题在于:
parentProperty(e) = 0;
parentProperty
是一个函数,就是这样。它不是真正的属性。它允许您从T
到long
- 这就是全部。它可以是任何东西 - 假设Func<string, long>
返回x.Length * 5
。 “设置”到(比如说)3?
如果您希望设置一个值,则需要一个操作,例如
public static List<T> Fix<T>(this List<T> enumeration,
Func<T, long> idProperty,
Func<T, long> parentGetter,
Action<T, long> parentSetter)
{
enumeration = enumeration.Select(e =>
{
long parentId = parentGetter(e);
if (!enumeration.Any(x => idProperty(x) == parentId))
{
parentSetter(e, 0);
}
return e;
}).ToList();
return enumeration;
}
并将其称为:
Test.Fix(a, x => x.ID, x => x.Parent, (x, v) => x.Parent = v).Dump();
请注意,我已经更改了Any
中的逻辑,因为您当前的逻辑没有意义 - 它在测试中没有使用e
。
然而,这实际上并不是LINQ的好用 - LINQ是围绕没有副作用而设计的。鉴于您只返回与以前相同的元素,您可能不会返回任何内容,只需使用foreach
循环:
public static void Fix<T>(this List<T> enumeration,
Func<T, long> idProperty,
Func<T, long> parentGetter,
Action<T, long> parentSetter)
{
foreach (T item in enumeration)
{
long parentId = parentGetter(e);
if (!enumeration.Any(x => idProperty(x) == parentId))
{
parentSetter(e, 0);
}
}
}
我个人然后将其更改为:
public static void Fix<T>(this List<T> enumeration,
Func<T, long> idProperty,
Func<T, long> parentGetter,
Action<T, long> parentSetter)
{
HashSet<long> validIds = new HashSet<long>(enumeration.Select(idProperty));
foreach (T item in enumeration.Where(x => !validIds.Contains(parentGetter(x)))
{
parentSetter(e, 0);
}
}