最酷的C#LINQ / Lambdas技巧你曾经拉过吗?

时间:2008-08-26 19:00:22

标签: c# linq functional-programming lambda

看到一篇关于C#隐藏功能的帖子,但很多人都没有写过linq / lambdas的例子,所以......我想知道......

  

你见过/写过的C#LINQ和/或Lambdas /匿名代表的最酷(最优雅)是什么?

奖金,如果它也投入生产!

14 个答案:

答案 0 :(得分:28)

LINQ Raytracer肯定是我名单上的首位=)

我不太确定它是否优雅,但它绝对是我见过的最酷的linq表达式!

哦,只是非常清楚;我做了写它(Luke Hoban做了)

答案 1 :(得分:19)

一些基本功能:

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

如果您不知道如何使用它们,请不要做太多好事。为了了解这一点,您需要知道它们的用途:

答案 2 :(得分:17)

到目前为止,我遇到的最令人印象深刻的Linq实施是Brahma框架。

它可以用于使用'Linq to GPU'将并行计算卸载到GPU。您在linq中编写了一个“查询”,然后Brahma将其转换为HLSL(高级着色器语言),以便DirectX可以在GPU上处理它。

这个网站只允许我粘贴一个链接,所以试试这个来自dotnetrocks的网络广播:

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

Else google for Brahma Project,你会得到正确的页面。

非常酷的东西。

GJ

答案 3 :(得分:11)

Progress Reporting用于长时间运行的LINQ查询。在博客文章中,您可以找到一个扩展方法WithProgressReporting(),它允许您在执行时发现并报告linq查询的进度。

答案 4 :(得分:4)

答案 5 :(得分:4)

对我来说,代表(Func<T,R>Action<T>)和表达式(Expression<Func<T,R>> Expression<Action<T>>)之间的二元性是产生lambdas最聪明用法的原因。 / p>

例如:

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

注意:几周前我在网上看到了这个,然后丢失了链接,从那时起,这里和那里出现了一些变化,所以我担心我无法给出正确的归属。

答案 6 :(得分:3)

不是我的设计,但我已经使用了几次,一个打字开关声明:http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx

如果......如果......其他如果......保存我这么多...其他如果!语句

答案 7 :(得分:3)

实际上,我为生成Excel文档而感到自豪:{{3p>

答案 8 :(得分:2)

我最近刚做了一件事(有点疯狂,但很有趣):

答案 9 :(得分:1)

我试图想出一个很酷的方法来为我正在构建的网站构建导航控件。我想使用常规HTML无序列表元素(使用标准CSS "Sucker Fish" look)和顶部导航鼠标悬停效果,显示下拉项。我有一个sql依赖缓存的DataSet,有两个表(NavigationTopLevels&amp; NavigationBottomLevels)。然后,我只需创建两个具有所需属性的类对象(TopNav和SubNav)(TopNav类必须具有bottomnav项的通用列表 - &gt; List&lt; SubNav&gt; 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可以节省时间。

答案 10 :(得分:1)

我认为LINQ是.NET的一个重大改变,它是一个非常强大的工具
我在生产中使用LINQ to XML来解析和过滤来自6MB XML文件(具有20多个节点级别)的记录到两行代码的数据集中。

在LINQ之前,这将花费数百行代码和数天进行调试。

这就是我所说的优雅!

答案 11 :(得分:1)

也许不是最酷的,但最近我一直在使用它们我有一块代码块一遍又一遍地获得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块一千五百万次。

答案 12 :(得分:0)

使用属性:

private void WriteMemberDescriptions(Type type)
{
    var descriptions =
        from member in type.GetMembers()
        let attributes = member.GetAttributes<DescriptionAttribute>(true)
        let attribute = attributes.FirstOrDefault()
        where attribute != null
        select new
        {
            Member = member.Name,
            Text = attribute.Description
        };

        foreach(var description in descriptions)
        {
            Console.WriteLine("{0}: {1}", description.Member, description.Text);
        }
}

GetAttributes扩展方法:

public static class AttributeSelection
{
    public static IEnumerable<T> GetAttributes<T>(this ICustomAttributeProvider provider, bool inherit) where T : Attribute
    {
        if(provider == null)
        {
            throw new ArgumentNullException("provider");
        }

        return provider.GetCustomAttributes(typeof(T), inherit).Cast<T>();
    }
}

AttributeSelection是生产代码,还定义了GetAttributeHasAttribute。我选择在此示例中使用letwhere子句。

答案 13 :(得分:0)

通过INotifyingCollection进行OLINQ反应式LINQ查询 - 这些查询允许您(除其他事项外)对大型数据集进行实时聚合。

https://github.com/wasabii/OLinq