zoukankan      html  css  js  c++  java
  • 谈谈LINQ的缺点

    概要:

    ·LINQ的实质是什么

    ·LINQ的问题是将复杂的问题简单化,让简单的问题复杂化

    ·LINQ喧宾夺主:

    - Lambda的抽象能力和描述能力大于LINQ

    - 扩展方法给程序员带来的好处也是强于LINQ

    ·目前C#中的Lambda和扩展方法是半完成的半吊子状态

    上面这些观点我以前的随笔中也出现过,这次乘着讨论LINQ的东风,详细深入的讨论一下。

    1 LINQ的实质是什么

    在远古时代,编程等于数据结构加算法,在现今时代,编程等于实体加策略。LINQ是一种接近于自然语言的针对Collection的策略(叫delegate也好,Functor也好)组合的描述。

    - LINQ可能(非可以!)节省代码量

    - LINQ可能(非可以!)具备更加的可读性

    - LINQ仅限于对Collection的操作

    2 LINQ的问题是将复杂的问题简单化,让简单的问题复杂化

    对于简单的策略组合问题,Lambda加上静态方法以及Collection的原有方法,可以提供和LINQ一样简单的、可读性一样好的解决方案。据说MSDN上不提倡直接用LINQ命名空间下的扩展方法,不过我觉得在大多数情况下直接用这些扩展方法比直接用LINQ更直接明了。

    对于复杂的策略组合问题,LINQ是有优势的,可以将复杂的集合操作简单化。

    问题在于:

    i)在程序开发中,绝大部分对Collection的操作都是简单操作,这些操作LINQ相比Lambda+现有方法+扩展方法并没有优势

    ii)少部分对Collection的复杂操作一般来说都是需要封装的,对外提供简单的接口调用。这些部分,用LINQ会有优势。不过,LINQ的描述能力还是有限的,很多更复杂的操作,LINQ描述不了。对于我来说,这样的需求已经好几个项目没遇上过了,遇上的话,用硬编码所花的时间也可以接受,不必要花时间去学LINQ

    3LINQ的喧宾夺主问题

    LINQ的光芒将Lambda表达式和扩展方法给掩盖住了,有点喧宾夺主的味道。如果让我来区分几个之间的区别,Lambda表达式和扩展方法应该属于战略层面的扩展,LINQ属于战术层面的。

    先看Lambda表达式,Lambda表达式天生就是描述策略组合的,它的可读性和LINQ差不多,它的描述能力却比LINQ强大很多,它和图灵机是等价的,而LINQ背后的关系数学的计算能力是很有限的。

    再看扩展方法。不知道大家是否还记得这个词:AOP。现实中,AOP的讨论大多集中于实做成面而不是思想层面。从思想层面来说,AOP就是将相关的东西通过某种方式集中的展现与处理。比如说,我们在IDE中,输入一个变量,再输入一个“.”,那么关于这个变量的操作就集中的展现给我们任由我们选择,这一点我觉得也应该属于AOP

    在编码当中,很多时候我们需要对一个类进行修饰,这些修饰类一多的时候,很难集中处理,我们经常忘记有哪些修饰类,修饰类之间的公用也不好处理。扩展方法使我们能够以AOP的范式来对类和对象进行修饰。在IDE中,我们一打“.”,这些修饰就AOP的展示给我们了。扩展方法还可以有一些更激进的应用,只不过微软目前没给我们。

    4C#目前Lambda表达式和扩展方法的不足之处

    目前C#Lambda表达式处于太监状态:不能推演类型。这样一来,撰写复杂的策略操作组合时需要写很长很长,嵌套一层又一层的类型定义,如此在复杂的策略组合时,使用Lambda表达式就很费事了。真不知道M$怎么想的,难道是给F#留路子?

    扩展方法的遗憾之处是没法对属性进行扩展,我不熟悉CLR底层实现,但如果能对属性进行扩展,然后使用某种机制使扩展方法和扩展属性在反射层面也能被当作一般属性和一般方法进行处理就更好了。这样的话,几乎全部的对类的修饰都可以通过扩展方法来进行。倒是向动态语言靠拢了。恩,等4.0再看看。

     

    俺的选择:

    结合以上讨论,俺在工作中是放弃应用LINQ了。主要觉得花费那时间去学习,所节省的时间未必有学习花的时间多。Lambda表达式和扩展方法倒是用的挺多。

    俺迫切需要动态代理功能。别人都是AOP需要,俺是在用泛型时需要。

    比如,Winform下的 ToolStripComboBox ComboBox 类,很多方法和属性名称一样,我需要取出一些值,将这些值绑定到ToolStripComboBoxComboBox上。这些值可能有1000多个,因此只在***BoxItem中绑定最常见的几个,然后再加上一条“选择其它”。为此,我需要写两份几乎一模一样的代码,邪恶啊。。。。。。ToolStripComboBox ComboBox 没有公共接口,不用反射没法搞啊,用反射。。。,俺还是复制粘贴吧。

    俺需要这样的一种动态代理:

    假定有一个接口:

        public interface TInterface
        {
            String A { 
    getset; }
            String B();
        }

    一个类

        public class ClassA
        {
            
    public String A { getset; }
            
    public String B()
            {
                
    return String.Empty;
            }
        }

    和一个类工厂:

        public sealed class TypeTemplate
        {
            
    public static T Create<T>(Object instance) where T : class
            {
                
            }
        }

    这个代理类可以用一个动态生成的类的实例将ClassA实例打包一下,使其适应Tinterface。这样来弥补C#的泛型不能实现编译时多态的问题,来减少代码的重复,可以充分发挥出泛型的威力了。

    更进一步,如果动态类与被代理的类的属性和方法签名不一致的话,能够手动添加之间的映射关系,实用性就更强了。

    关于策略的组合,设计模式中策略模式是一种做法。泛型编程中泛型是另一种做法。Lambda表达式是另外一种做法。目前C#的泛型、Lambda深入应用的话,总是缺点什么。不爽。

    版权所有,欢迎转载
  • 相关阅读:
    lcd驱动解析(二)
    php参数引用
    Curl来做冒烟测试
    TIB自动化测试工作室QTP脚本汇总比较有价值
    使用QTP自动化 DZ消息复选框选择实例!
    正则表达式30分钟
    sqlserver查询数据库中有多少个表
    怎样获取页面上所有链接的名称和url
    Curl 来做自动跟踪重定向
    sqlserver2008 删除指定表
  • 原文地址:https://www.cnblogs.com/xiaotie/p/1369945.html
Copyright © 2011-2022 走看看