1

我做了这个扩展,我必须修改源列表中一个属性的值。我遇到的问题是它不会改变源列表中的值,项目的值改变得很好。

这是我的扩展:

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;在 a中使用,foreach但更改“来源”会更有用。

谢谢。

4

2 回答 2

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;
    }
}
于 2013-09-06T14:15:37.440 回答
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;
于 2013-09-06T14:14:19.923 回答