简体   繁体   中英

Can I call a function in a lambda expression?

I would like to do the following but I don't think this will work:

.OrderByDescending(s => Score(s)), ...


private double Score(Story s)
        {
            DateTime now = DateTime.Now;
            TimeSpan elapsed = now.Subtract(s.PostedOn);
            double daysAgo = elapsed.TotalDays;

            return s.Votes.Count + s.Comments.Count - daysAgo;
        }

a. should this work? b. if not, do I need to query for the stories and then sort them by the score?

Yes, that should work if the sequence is a sequence of Story items; what problem are you having? Note that if Score doesn't apply to any instance, it might be worth making it static.

Another option is to make the Score() method an instance method on a Story , or an extension method.

Note that this only applies to LINQ-to-Objects; if you are using LINQ-to-SQL / LINQ-to-Entities, etc you either need to use a lambda for the whole thing, or (in LINQ-to-SQL only) use a UDF-mapped function (on the data-context) to calculate the value.

Example (LINQ-to-Objects) with your original syntax:

using System.Linq;
using System;
class Story { // declare type
    public DateTime PostedOn { get; set; }
    // simplified purely for convenience
    public int VotesCount { get; set; }
    public int CommentsCount { get; set; }
}
static class Program {
    static void Main() {
        // dummy data
        var data = new[] {
            new Story { PostedOn = DateTime.Today,
                VotesCount = 1, CommentsCount = 2},
            new Story { PostedOn = DateTime.Today.AddDays(-1),
                VotesCount = 5, CommentsCount = 22},
            new Story { PostedOn = DateTime.Today.AddDays(-2),
                VotesCount = 2, CommentsCount = 0}
        };
        var ordered = data.OrderByDescending(s=>Score(s));
        foreach (var row in ordered)
        {
            Console.WriteLine(row.PostedOn);
        }
    }

    private static double Score(Story s) {
        DateTime now = DateTime.Now;
        TimeSpan elapsed = now.Subtract(s.PostedOn);
        double daysAgo = elapsed.TotalDays;
        // simplified purely for convenience
        return s.VotesCount + s.CommentsCount - daysAgo;
    }
}

Add a this (ie Score(this Story s) ), and you can use:

.OrderByDescending(s=>s.Score())

On a minor note, you may write

.OrderByDescending(Score)

since "Score"'s signature fulfills the required signature.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM