我做了这个扩展,我必须修改源列表中属性的值。我遇到的问题是它不会更改源列表中的值,项目的值会更改。
这是我的扩展名:
public static IEnumerable<TSource> SetIndex<TSource, TResult>(
this IEnumerable<TSource> source,
Expression<Func<TSource, TResult>> propertyExpression)
{
MemberExpression body = propertyExpression.Body as MemberExpression;
if (body == null)
{
return source;
}
PropertyInfo propertyInfo = body.Member as PropertyInfo;
if (propertyInfo == null || propertyInfo.PropertyType != typeof(int))
{
return source;
}
string propertyName = body.Member.Name;
int index = 0;
foreach (TSource item in source)
{
propertyInfo.SetValue(item, index++, null);
}
return source;
}
这是我要测试的代码:
public class Persona
{
public string Name { get; set; }
public string Lastname { get; set; }
}
public class PersonaGroup
{
public string Lastname { get; set; }
public int Count { get; set; }
public int Index { get; set; }
}
IList<Persona> listPersonas = new List<Persona>()
{
new Persona{ Lastname = "Lopez", Name = "Tilo" },
new Persona{ Lastname = "Dominguez", Name = "Raul" },
new Persona{ Lastname = "Martinez", Name = "Manuel" },
new Persona{ Lastname = "Martinez", Name = "Rogelio" },
new Persona{ Lastname = "Lopez", Name = "Roberto" },
new Persona{ Lastname = "Martinez", Name = "Alen" },
new Persona{ Lastname = "Lopez", Name = "Mario" },
new Persona{ Lastname = "Dominguez", Name = "Duran" },
new Persona{ Lastname = "Martinez", Name = "Maria" },
new Persona{ Lastname = "Dominguez", Name = "Marta" },
new Persona{ Lastname = "Lopez", Name = "Pedro" },
new Persona{ Lastname = "Dominguez", Name = "Martin" },
new Persona{ Lastname = "Dominguez", Name = "Diego" },
new Persona{ Lastname = "Lopez", Name = "El" }
};
IList<PersonaGroup> listPersonasGroups = listPersonas
.GroupBy(p => p.Lastname)
.Select(pg => new PersonaGroup { Lastname = pg.Key, Count = pg.Count() })
.SetIndex(pg => pg.Index)
.ToList();
foreach (PersonaGroup personaGroup in listPersonasGroups)
{
Console.WriteLine("{0} - {1} : {2}",
personaGroup.Index,
personaGroup.Count,
personaGroup.Lastname);
}
Console.ReadKey();
结果:
0 - 5 : Lopez
0 - 5 : Dominguez
0 - 4 : Martinez
当我写了我的问题时,我发现问题是在使用Select
时,但我不知道如何解决它或为什么我无法修改列表。
我知道我可以在yield return item;
中使用foreach
,但更改“来源”会更有用。
感谢。
答案 0 :(得分:3)
您可以使用标准LINQ方法执行所需操作:
IList<PersonaGroup> listPersonasGroups = listPersonas
.GroupBy(p => p.Lastname)
.Select((pg, i) => new PersonaGroup {
Lastname = pg.Key,
Count = pg.Count(),
Index = i
})
.ToList();
带有Select
参数的 Func<TSource, int, TResult>
重载与您的自定义扩展方法类似:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (selector == null)
{
throw Error.ArgumentNull("selector");
}
return Enumerable.SelectIterator<TSource, TResult>(source, selector);
}
private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
{
int num = -1;
checked
{
foreach (TSource current in source)
{
num++;
yield return selector(current, num);
}
yield break;
}
}
答案 1 :(得分:1)
问题在于这段代码:
foreach (TSource item in source)
{
propertyInfo.SetValue(item, index++, null);
}
return source;
source
被推迟IEnumerable,你可以枚举两次。在return source;
中根本没有变化。例如,您可以将其更改为:
var array = source.ToArray();
foreach (TSource item in array)
{
propertyInfo.SetValue(item, index++, null);
}
return array;