幕后的C#lambda

幕后的C#lambda,c#,lambda,C#,Lambda,对于没有使用经验的人来说,以下代码让它看起来很神奇: int totalScore = File.ReadLines(@"c:/names.txt") .OrderBy(name => name) .Select((name, index) => { int score = name.AsEnumerable().Select(character => character - 9

对于没有使用经验的人来说,以下代码让它看起来很神奇:

int totalScore = File.ReadLines(@"c:/names.txt")
            .OrderBy(name => name)
            .Select((name, index) => {
                int score = name.AsEnumerable().Select(character => character - 96).Sum();
                score *= index + 1;
                return score;
            })
            .Sum();
是什么使名称引用集合中的元素,更有趣的是,是什么使索引引用元素的索引


因为这显然不是一个魔术,除了理解(可能还有其他什么?)之外,Lambda表达式是如何工作的?

这实际上与lambdas无关,您可以同样轻松地向它传递一个方法,该方法使用字符串和
int
参数。您可以编写自己的select实现:

public static class TestClass
{
    public static IEnumerable<TReturnType> DoSelect<TSourceType, TReturnType>(this IEnumerable<TSourceType> source, Func<TSourceType, int, TReturnType> action)
    {
        int i = 0;
        foreach(var row in source)
            yield return action(row, i++);
    }
}
您也可以在不使用lambdas的情况下为select编写代码:

private int MyFunction(string name, int index)
{
    int score = name.AsEnumerable().Select(character => character - 96).Sum();
    score *= index + 1;
    return score;
}

int totalScore = File.ReadLines(@"c:/names.txt")
        .OrderBy(name => name)
        .Select(MyFunction)
        .Sum();

没有魔法,所有的
Select
都在执行

    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 SelectIterator<TSource, TResult>(source, selector);
    }

    static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) {
        int index = -1;
        foreach (TSource element in source) {
            checked { index++; }
            yield return selector(element, index);
        }
    }
这和

private int SomeFunction(string name, int index)
{
    int score = name.AsEnumerable().Select(character => character - 96).Sum();
    score *= index + 1;
    return score;
}
因此,
Select
传入
name
index
值,并调用您的函数

    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 SelectIterator<TSource, TResult>(source, selector);
    }

    static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) {
        int index = -1;
        foreach (TSource element in source) {
            checked { index++; }
            yield return selector(element, index);
        }
    }
(name, index) => {
            int score = name.AsEnumerable().Select(character => character - 96).Sum();
            score *= index + 1;
            return score;
        }
private int SomeFunction(string name, int index)
{
    int score = name.AsEnumerable().Select(character => character - 96).Sum();
    score *= index + 1;
    return score;
}