【问题标题】:Coolest C# LINQ/Lambdas trick you've ever pulled?您使用过的最酷的 C# LINQ/Lambdas 技巧?
【发布时间】:2010-09-06 22:19:44
【问题描述】:

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

您见过/写过的 C# LINQ 和/或 Lambdas/匿名委托的最酷(最优雅)的用法是什么?

如果它也已投入生产,将获得奖励!

【问题讨论】:

    标签: c# linq functional-programming lambda


    【解决方案1】:

    LINQ Raytracer 无疑是我的首选 =)

    我不太确定是否符合优雅的条件,但它肯定是我见过的最酷的 linq 表达式!

    哦,而且要非常清楚;我确实没有写过它(Luke Hoban 做过)

    【讨论】:

    • 让我想起了 SQL 中的 Madlebrot:thedailywtf.com/Articles/…
    • 我听过 Luke 的播客,他说他用编写光线追踪器来“测试”一门新语言。因此,当 LINQ 出现时,他只需将他的标准“测试”应用于它,LINQ Raytracer 就诞生了。
    【解决方案2】:

    一些基本功能:

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

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

    【讨论】:

    • 为什么这仍然不是 .net 标准功能?
    • 看起来像 Zip() linq 扩展方法。
    【解决方案3】:

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

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

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

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

    其他 google 搜索 Brahma Project,你会得到正确的页面。

    非常酷的东西。

    GJ

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:
        【解决方案6】:

        对我来说,代表(Func&lt;T,R&gt;Action&lt;T&gt;)和表达式(Expression&lt;Func&lt;T,R&gt;&gt;Expression&lt;Action&lt;T&gt;&gt;)之间的对偶性是 lambda 最聪明的用途。

        例如:

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

        注意:我最初是几周前在网上看到的,然后失去了链接,从那时起到处出现了许多变体,所以恐怕我无法给出正确的归属。

        【讨论】:

          【解决方案7】:

          实际上,我为生成 Excel 文档感到非常自豪:http://www.aaron-powell.com/linq-to-xml-to-excel

          【讨论】:

          • 链接失效了?
          • @asgerhallas - 我已将链接更新到我更新后的网站上的位置
          【解决方案8】:

          不是我的设计,但我用过几次,一个类型化的开关语句:http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx

          如果... else if... else if... else if... 救了我这么多!陈述

          【讨论】:

          • 哇!总是对 ppl 的想法印象深刻 555 也许我们生活在一个打字世界太多了。
          • 自 C#7 以来,这种方法实际上已经过时了。
          【解决方案9】:

          我最近做了一件(有点疯狂,但很有趣)这样的事情:

          【讨论】:

            【解决方案10】:

            我试图想出一种很酷的方法来为我正在构建的网站构建导航控件。我想使用带有顶部导航鼠标悬停效果的常规 HTML 无序列表元素(使用标准 CSS "Sucker Fish" look)来显示下拉项目。我有一个带有两个表(NavigationTopLevels 和 NavigationBottomLevels)的 sql 依赖缓存数据集。然后我所要做的就是创建两个类对象(TopNav 和 SubNav),它们具有少数必需的属性(TopNav 类必须有一个底部导航项的通用列表 -> List SubItems)。


            var TopNavs = 来自 ds.NavigationTopLevels 中的 n 选择新的 TopNav { NavigateUrl = String.Format("{0}/{1}", tmpURL, n.id), 文本 = n.文本, id = n.id, 子项 = 新列表( 来自 ds.NavigationBottomLevels 中的 si 其中 si.parentID == n.id 选择新的子导航 { id = si.id, 级别 = si.NavLevel, NavigateUrl = String.Format("{0}/{1}/{2}", tmpURL, n.id, si.id), parentID = si.parentID, 文本 = si.Text } ) }; 列表 TopNavigation = TopNavs.ToList();

            它可能不是“最酷”的,但对于很多想要动态导航的人来说,不必在随之而来的通常循环逻辑中混混,真是太好了。在这种情况下,LINQ 可以节省时间。

            【讨论】:

              【解决方案11】:

              我认为 LINQ 是对 .NET 的重大改变,它是一个非常强大的工具。

              我在生产中使用 LINQ to XML 以两行代码将 6MB XML 文件(具有 20 多个节点级别)中的记录解析和过滤到数据集中。

              在 LINQ 之前,这将需要数百行代码和数天的时间来调试。

              这就是我所说的优雅!

              【讨论】:

              • 肯定是 :-) 我喜欢它。
              • 让我想知道为什么我们要等这么久才能出现这样的技术?
              【解决方案12】:

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

              【讨论】:

                【解决方案13】:

                使用属性:

                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 子句。

                【讨论】:

                  【解决方案14】:

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

                  https://github.com/wasabii/OLinq

                  【讨论】:

                    猜你喜欢
                    • 2012-01-31
                    • 2010-10-13
                    • 2011-04-27
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-04-30
                    • 2011-12-08
                    • 2010-11-17
                    相关资源
                    最近更新 更多