Самый крутой трюк C # LINQ / Lambdas, который ты когда-либо использовал? - PullRequest
42 голосов
/ 26 августа 2008

Видел пост о скрытых функциях в C #, но не так много людей написали пример linq / lambdas, так что ... интересно ...

Какое самое крутое (как и самое элегантное) использование C # LINQ и / или Lambdas / анонимных делегатов, которых вы когда-либо видели / писали?

Бонус, если он тоже запущен в производство!

Ответы [ 14 ]

28 голосов
/ 26 августа 2008

LINQ Raytracer определенно возглавляет мой список =)

Я не совсем уверен, можно ли считать его элегантным, но это, безусловно, самое крутое выражение linq, которое я когда-либо видел!

О, и просто чтобы быть предельно ясным; Я не написал ( Люк Хобан сделал)

19 голосов
/ 26 августа 2008

Некоторые основные функционалы:

public static class Functionals
{
    // One-argument Y-Combinator.
    public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F)
    {
        return t => F(Y(F))(t);
    }

    // Two-argument Y-Combinator.
    public static Func<T1, T2, TResult> Y<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> F)
    {
        return (t1, t2) => F(Y(F))(t1, t2);
    }

    // Three-arugument Y-Combinator.
    public static Func<T1, T2, T3, TResult> Y<T1, T2, T3, TResult>(Func<Func<T1, T2, T3, TResult>, Func<T1, T2, T3, TResult>> F)
    {
        return (t1, t2, t3) => F(Y(F))(t1, t2, t3);
    }

    // Four-arugument Y-Combinator.
    public static Func<T1, T2, T3, T4, TResult> Y<T1, T2, T3, T4, TResult>(Func<Func<T1, T2, T3, T4, TResult>, Func<T1, T2, T3, T4, TResult>> F)
    {
        return (t1, t2, t3, t4) => F(Y(F))(t1, t2, t3, t4);
    }

    // Curry first argument
    public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(Func<T1, T2, TResult> F)
    {
        return t1 => t2 => F(t1, t2);
    }

    // Curry second argument.
    public static Func<T2, Func<T1, TResult>> Curry2nd<T1, T2, TResult>(Func<T1, T2, TResult> F)
    {
        return t2 => t1 => F(t1, t2);
    }

    // Uncurry first argument.
    public static Func<T1, T2, TResult> Uncurry<T1, T2, TResult>(Func<T1, Func<T2, TResult>> F)
    {
        return (t1, t2) => F(t1)(t2);
    }

    // Uncurry second argument.
    public static Func<T1, T2, TResult> Uncurry2nd<T1, T2, TResult>(Func<T2, Func<T1, TResult>> F)
    {
        return (t1, t2) => F(t2)(t1);
    }
}

Не делай много пользы, если не умеешь их использовать. Чтобы узнать это, вам нужно знать, для чего они:

17 голосов
/ 18 августа 2009

Самая впечатляющая реализация Linq, с которой я когда-либо сталкивался, - это инфраструктура Brahma.

Может использоваться для разгрузки параллельных вычислений на графический процессор с помощью 'Linq to GPU'. Вы пишете «запрос» в linq, а затем Brahma переводит его в HLSL (высокоуровневый язык шейдеров), чтобы DirectX мог обрабатывать его на GPU.

Этот сайт позволит мне вставить только одну ссылку, поэтому попробуйте эту веб-трансляцию с dotnetrocks:

http://www.dotnetrocks.com/default.aspx?showNum=466

Еще Google для проекта Брахма, вы получите правильные страницы.

Очень классные вещи.

GJ

11 голосов
/ 17 сентября 2008

Отчет о прогрессе для длительных запросов LINQ. В сообщении блога вы можете найти метод расширения WithProgressReporting (), который позволяет вам обнаруживать и сообщать о ходе выполнения запроса linq.

4 голосов
/ 19 августа 2009

Для меня двойственность между делегатами (Func<T,R>, Action<T>) и выражениями (Expression<Func<T,R>> Expression<Action<T>>) - вот что порождает наиболее умное использование лямбд.

Например:

public static class PropertyChangedExtensions
{
    public static void Raise(this PropertyChangedEventHandler handler, Expression<Func<object>> propertyExpression)
    {
        if (handler != null)
        {
            // Retrieve lambda body
            var body = propertyExpression.Body as MemberExpression;
            if (body == null)
                throw new ArgumentException("'propertyExpression' should be a member expression");

            // Extract the right part (after "=>")
            var vmExpression = body.Expression as ConstantExpression;
            if (vmExpression == null)
                throw new ArgumentException("'propertyExpression' body should be a constant expression");

            // Create a reference to the calling object to pass it as the sender
            LambdaExpression vmlambda = Expression.Lambda(vmExpression);
            Delegate vmFunc = vmlambda.Compile();
            object vm = vmFunc.DynamicInvoke();

            // Extract the name of the property to raise a change on
            string propertyName = body.Member.Name;
            var e = new PropertyChangedEventArgs(propertyName);
            handler(vm, e);
        }
    }
}

Тогда вы можете "безопасно" внедрить INotifyPropertyChanged, позвонив

if (PropertyChanged != null)
    PropertyChanged.Raise( () => MyProperty );

Примечание. Сначала я видел это в Интернете несколько недель назад, а затем потерял ссылку, и с тех пор тут и там возникло множество вариантов, поэтому я боюсь, что не могу дать надлежащую атрибуцию.

3 голосов
/ 17 сентября 2008

На самом деле, я очень горжусь этим для создания документов Excel: http://www.aaron -powell.com / linq-to-xml-to-excel

3 голосов
/ 17 сентября 2008

Не мой дизайн, но я использовал его несколько раз, оператор с типизированным переключателем: http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx

Спасло меня так много, если ... еще, если ... еще, если ... еще, если! заявления

2 голосов
/ 28 ноября 2008

Недавно я сделал одну (немного сумасшедшую, но интересную) вещь:

1 голос
/ 28 апреля 2010

Возможно, не самый крутой, но в последнее время я использую их каждый раз, когда у меня есть блок кода, который снова и снова получает C + Pd только для изменения нескольких строк. Например, выполнение простых команд SQL для извлечения данных может быть выполнено так:

SqlDevice device = GetDevice();

return device.GetMultiple<Post>(
    "GetPosts",
    (s) => {
        s.Parameters.AddWithValue("@CreatedOn", DateTime.Today);

        return true;
    },
    (r, p) => {
        p.Title = r.Get<string>("Title");

        // Fill out post object

        return true;
    }
);

Который мог бы вернуть список сообщений, которые были созданы сегодня. Таким образом, мне не нужно копировать и вставлять блок try-catch-finally пятнадцать миллионов раз для каждой команды, объекта и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...