[C#] Самый классный C # LINQ / Lambdas трюк, который вы когда-либо вытаскивали?


Answers

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

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);
    }
}

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

Question

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

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

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




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




Для меня двойственность между делегатами ( 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 );

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




OLINQ реактивные запросы LINQ над INotifyingCollection - это позволяет вам (помимо всего прочего) выполнять агрегацию в реальном времени против больших наборов данных.

https://github.com/wasabii/OLinq







Возможно, это не самый классный, но в последнее время я использую их в любое время, когда у меня есть блок кода, который снова и снова запускает 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 пятнадцать миллионов раз для каждой команды, объекта и т. Д.




Я пытался придумать классный способ создания навигационного элемента управления для сайта, который я строил. Я хотел использовать регулярные неупорядоченные элементы списка HTML (с использованием стандартного CSS «Sucker Fish» ) с эффектом «мышь » с верхней навигацией, который показывает выпадающие элементы. У меня был sql-зависимый кешированный DataSet с двумя таблицами (NavigationTopLevels & NavigationBottomLevels). Тогда мне пришлось создать два объекта класса (TopNav & SubNav) с несколькими требуемыми свойствами (класс TopNav должен был иметь общий список элементов bottomnav -> List <SubNav> SubItems).


var TopNavs = from n in ds.NavigationTopLevels select new TopNav { NavigateUrl = String.Format("{0}/{1}", tmpURL, n.id), Text = n.Text, id = n.id, SubItems = new List<SubNav>( from si in ds.NavigationBottomLevels where si.parentID == n.id select new SubNav { id = si.id, level = si.NavLevel, NavigateUrl = String.Format("{0}/{1}/{2}", tmpURL, n.id, si.id), parentID = si.parentID, Text = si.Text } ) }; List<TopNav> TopNavigation = TopNavs.ToList();

Это может быть не «классный», а для многих людей, которые хотят иметь динамичную навигацию, ее сладость не должна путаться вокруг в обычной логике цикла, которая приходит с этим. LINQ - это что-то в этом случае.