Domain-Specific Languages (1)

  • 第16页
    DSL是一种面向特定领域与使用场景的语言,其实质是一种程序配置的外观。 设计良好的程序通常拥有一种普适的模型,再基于模块的装配与组织实现特定的功能。DSL用于描述程序的配置,通常分为Internal DSL和External D...

RESTful Web Services中文版 (8) 更多

  • 第113页
    资源通常包括: 1. 特别定义的资源或入口 2. 服务暴露的每个对象所对应的资源 3. 特别的算法的结果的资源 命名资源时可以: 1. 用路径变量表达层次结构 2. 用标点表达非层次结构,当作用域的先后有关时用"..;.
  • 第108页
    由于rest只支持6种操作,因此在普通面向对象中的操作也将变成一种资源。 如读者订阅栏目,则没有订阅这个动作,而是将订阅看成是一种附属的资源,需要创建,可以删除。
  • 第99页
    Put与Post的区别 都能用于将应用状态上传至资源状态。 前者用于上传或修改资源,uri由客户端指定;后者用于上传及追加从属资源,uri由服务器指定。 Get与Head应当是安全的,即调用始终不影响服务器状态 Put与Del...
  • 第95页
    连通性: 指资源的表示之间能够相互链接,客户端应用状态在服务提供的链接的指引之下发生转移。 连通性将使应用有更好的易用性,便于程序在资源之间切换。
  • 第93页
    虽然请求的元数据也能影响请求的返回结果,但还是应当尽可能地将信息放在uri中。因此uri能在客户端与应用之间传播,但元数据则不行。 比如对于资源表示,可以通过显式在uri中指明表示形式,也能通过元数据中的默认..
  • 第86页
    可寻址性: 即不同资源的uri之间应存在一定的规则,不同的资源由不同的uri指示。 无状态性: 每个http请求都是孤立的,请求中包含所有需要的信息,不需要依赖之前请求提供的信息。状态可以简化单个请求,但会使整...
  • 第83页
    同一个数据可以被不同的uri指向,但uri间的语义不相同,因此属于两个资源。 若有多个语义相同的uri指向同一个资源,则可以在http返回303指示出真正的uri。 一个uri只能指向一个资源,但可以返回多个资源的信息(请...
  • 第13页
    Rest: 面向资源的架构,uri代表一个资源。使用http方法表示操作的方法信息,使用路径表示方法的作用域。 RPC: uri代表一个处理进程。将操作方法信息和作用域信息均保存在http内容实体中。 混合模式: uri代表...

敏捷软件开发 (12) 更多

  • 第253页
    对于需要实例化而产生的耦合,可以使用对象工厂的方法进行解耦。 即抽象出工厂接口作为单独的包,并在具体类包的内部实现此工厂接口,便能将依赖倒置。
  • 第225页
    包的设计原则: 内聚性原则: 1. 重用发布等价原则。即重用的粒度是发布的粒度 2. 共同重用原则。即一个包中的类应当共同被重用,而不是仅重用其中的一部分类。 3. 共同封闭原则。即一个变化若对一个包产生影响..
  • 第178页
    策略也未必就一定是单例的。 策略对象中除了包含封装的行为外,还能拥有不同实体拥有的策略的不同变量,从而便策略变化非单例的。可以解决有继承倾向但是不应使用继承的情况。
  • 第127页
    接口隔离原则: 不应当让客户端依赖于它们不使用的方法。对于一个胖类,应使用多个接口将其中不同的功能划分开来,从而客户端程序便可以仅依赖于相应的接口。 若同时需要传入多个接口时,最好还是使用多个形参的形...
  • 第117页
    依赖倒置原则: 1. 高层模块不依赖低层模块 2. 抽象不依赖实现,实现依赖抽象 倒置不仅仅是依赖关系的倒置,也是接口所有权的倒置。在使用DIP时,往往是客户层拥有此接口,而服务层是此接口的具体实现。 即: ...
  • 第107页
    里氏替换原则: is-a的关系是基于行为方式而言的,并非基于单纯概念上的考虑。在基于契约的设计中,子类只能使用相等或更弱的前置条件以及相等或更强的后置条件进行行为的约束。 对于违反LSP的设计,可以考虑将其..
  • 第90页
    单一职责原则:职责定义为引发变化的动机。若存在独立变化的部分或动机,则说明有多于一个职责的存在。 开闭原则:可以通过扩展改变行为,但不能修改现有代码。当预测到某种变化时,可以使用抽象来封装它。在敏捷开...
  • 第82页
    敏捷开发的设计 设计腐化的原因是由于需求发生了设计预期以外的改变,并且改动很急迫,开发人员对设计的原则并不熟悉。 在敏捷开发的设计中,由于不会对设计预设计,因此不需要一个成熟的初始设计。但在每次迭代时...
  • 第25页
    单元测试 采用测试驱动开发方式,可以1.对程序的正确性进行基本测试;2.使编程的视角由开发者转变为调用者,更强调接口的作用,实现解耦和更良好的设计。 验收测试 采用自动化的验收测试,在无用户界面的情况下进...
  • 第15页
    简单的设计 每次仅考虑实现此次迭代的用户素材。但会始终通过良好的设计来使此次迭代处于最优状态;通过重构解决代码腐化和更新。 隐喻 指系统的愿景和全局视图。由于每次迭代只开发系统的一小部分,因此通过全局...
  • 第20页
    素材计划 开发人员将客户提供的素材及需求点设置分值,每次迭代时向客户提供此次成本的总分值,由客户指定不超过分值上限的素材进行实现。点数间接地反映了所需时间的长短,应当规定一个速度,如:2点需要一天的时..
  • 第4页
    敏捷开发原则: 1. 强调个体和人之间的交互 2. 持续更新的软件比文档重要:缺少文档的软件是灾难;但文档过多一会导致编写文档花费精力, 二是维持文档与代码一致更费精力。通过团队之间手把手的交流来培训新的成..

Effective Java (73) 更多

  • 第312页
    Item78:使用序列化代理对象 若对象需要实现可序列化时,可以使用序列化此对象的代理对象,让代理对象实现可序列化接口,这样可以避免对象本身的复杂性。 但对于复杂对象,如包含有引用循环等,则不适合。并且被代...
  • 第289页
    Item74:谨慎实现Serializable 1. 由于实现了Serializable后,会限制类型实现的变化,因为所有的内部实现均会序列化保存到客户端中。 2. 增加bug和漏洞的可能性。 3. 增加发布新版本时测试的工作量。 为继承而设...
  • 第288页
    Item73:避免使用ThreadGroup类线程、锁、监视器 ThreadGroup API自身不一定是线程安全的;要表示一组线程时,应当使用Executor Service线程池代替
  • 第286页
    Item72:不要依赖任务调度 线程在不进行工作时需要sleep,不要busy waiting. 但不要使用Thread.yield。因为这不保证语义,在不同JVM上的运行情况不同。
  • 第282页
    Item71:谨慎使用延时加载 只有当对象仅被一部分行为使用,并且对象的初始化很昂贵时,才需要延时加载。 因为延时加载会使得加载变慢,并且让代码难以阅读。 如果要对成员变量进行延迟加载,需要加入同步块,使用...
  • 第278页
    Item70:在文档中说明类型的线程安全级别 1. 不可变对象:无需外部同步 2. 无条件线程安全:是可变的对象,但在对象内部机制中已经考虑了并发同步情况,无需外部同步 3. 部分线程安全:有一部分方法是线程不安全..
  • 第273页
    Item69:相对于wait, notify,尽量使用Concurrent包的机制 主要包含三部分: 1. Executor 框架 2. 同步Collection 3. Synchronizer 对于同步Collection,不必再为其加锁,因为这些Collection总是考虑同步的情况...
  • 第271页
    Item68:相对于Thread类,尽量使用Executor和Task 使用Thread时,思路依然是面向实现的;但使用Task(Runnable及Callable)时,却将实现与工作任务分离,让concurrent包负责并发的实现,自己负责编写任务。可以让Ex...
  • 第265页
    Item67:避免过度的同步块 为了避免运行时出现的问题,在同步块中不要将控制流移交给客户端。即不能在同步块中使用可重写的方法、客户端提供的对象的方法。由于不确定这些外界对象的行为,因此有可能会引发死锁、co...
  • 第259页
    Item66:同步共享可变资源的访问 同步不仅能保证线程不会看见对象在状态变化过程中的不一致状态,并且能保证进入同步块的线程一定能看见其它线程状态改变的结果。 除了long和double以外,对于其它变量而言,读或写...
  • 第258页
    Item65:不要埋掉异常
  • 第256页
    Item64:实现对象的异常原子化 即虽然对象的方法在执行过程中抛出了异常(尤其是checkedException),但这个对象的状态依然是可用的,仍然是抛出异常以前的状态,不将异常的状态延续至调用后。这种机制称为异常的原...
  • 第254页
    Item63:在异常的toString方法中说明引起异常的原因、变量 可以显示地在构造方法传入这些参数以确保所有的信息都收集到。
  • 第252页
    Item62:为每一个抛出的checked异常使用@throw注释
  • 第250页
    Item61:使用异常翻译机制 下层抛出的异常一般需要被上层捕获,并且翻译成符合上层上下文的异常类型。可以在上层的新异常中将下层异常作为Cause参数传入新异常的构造中,以说明具体引起异常的原因。 否则,下层的..
  • 第248页
    Item60:尽可能使用已有的标准Exception 虽然IllegalArgumentException是最常用到的异常,但如果有更精确的Exception就要使用更精确的描述。 如输入参数是null时可以使用NullPointerException。类似的还有IndexOut...
  • 第246页
    Item59:不要滥用checkedException 当设计中准备申明抛出异常时,要同时满足以下两个条件: 1. 这个异常是无法通过正确调用API来避免的 2. 调用者对于这个异常可以在上层有更好的处理方法 若是两个条件中有一个..
  • 第244页
    Item58:使用checked异常处理可恢复的情况;使用runtime异常处理编程错误 若一个方法申明了checked异常的抛出,则说明这些异常情况是正常的方法的输出之一。方法的调用者遇到这些输出应当能够有正确的行为进行恢复..
  • 第241页
    Item57:仅在异常处使用异常机制 不要使用异常机制来做一般奇怪的事,也不应该使用异常机制来实现程序的控制流。
  • 第237页
    Item56:使用约定俗成的命名规范
  • 第234页
    Item55:避免过多的性能调试 一般情况下,人为的所谓性能上的优化往往会导致更多性能上的破坏。我们的目标是努力写“好”的程序,而非写快速的程序。如果一个“好”的程序不够快速,那么可以他的架构将允许模块在接...
  • 第233页
    Item54:合理使用本地方法 不要因为提高效率而使用本地方法,因为现代JVM的效率已经提高了很多。 而调用的本地方法万一出现错误,则可能导致整个程序的崩溃。
  • 第230页
    Item53:尽量使用接口代替反射 使用反射时甚至可以在被调用类在调用类编译时还未存在的情况下访问这些类。 主要有以下几个缺点: 1. 丧失了编译时的检测 2. 让代码看上去很凌乱 3. 反射的调用比普通调用要慢 ...
  • 第228页
    Item52:尽可能使用接口来指定输入类型
  • 第227页
    Item51:注意String连接时的问题
  • 第224页
    Item51:不要使用String来代替其它类型
  • 第221页
    Item49:尽可能使用int等未装箱的类型 和装箱的类型相比,未装箱的类型更快速,更节约空间,不可能产生null值。 要注意的是,由于在<和>时装箱类型会自动拆箱,因此可以得出正确的结果;但对于==而言却总是..
  • 第219页
    Item48:当需要精确结果时,不要使用float和double 可以使用BigDecimal来解决精度问题,但相比int和long存在两个缺陷:效率问题和调用的不便。 如果整数的数字长度不超过9位,可以使用int;不超过18可以使用long;...
  • 第215页
    Item47:尽可能地使用类库 通过使用类库,能更好地利用现有资深人士的成果和资源。不仅节省时间,还获得了很高的性能表现。 对于util, io, concurrent包需要有较好的了解
  • 第212页
    Item46:倾向于使用Foreach 因为在foreach中能够定义局部变量的名称,因此会显得更加简洁。 因此在实现对象的集合时,考虑实现Iterable,这样便可以在for循环中直接调用。
  • 第209页
    Item45:最小化局部变量的作用域 1. 在变量需要使用的时候再申明 2. 相对于while,更倾向于使用for循环。因为for循环允许定义局部变量,而while循环需要在外部定义变量,增加了额外的变量作用域。若不小心在后面代...
  • 第203页
    Item44:为公开的类型和方法编写javadoc 1. 为方法说明方法的前置、后置条件,以及方法的副作用 2. 对于为继承而设计的类,还要说明方法是如何运作的,调用了哪些可重写的方法 3. 还需要说明是否是线程安全的 4....
  • 第201页
    Item43:尽量返回空数组或字符串,而非null 不用担心每次返回空数组或字符串的资源消耗问题,因为长度为0的数组是不可变的,所以可以在多次调用中返回同一个空对象。
  • 第41页
    Item41:合理使用重载 方法的重写是动态绑定的,方法的重载是在编译时确定的,因此无法使用动态绑定的技术。拥有父类及子类两种重载类型的方法将在运行时产生预期之外的行为。 通常而言,不要使两个重载的方法具有...
  • 第189页
    Item40:设计良好的方法签名 1. 为其取恰当的名字:符合命名规范,并便于理解,与全局统一 2. 不要提供太多的便捷方法。太多的方法会令类的学习成本增加 3. 避免太长的方法参数。当相同的方法的参数序列反复出现..
  • 第184页
    Item39:在需要的时候进行防御性拷贝 1. 当需要将外部的可变对象保存至当前对象中时(如构造函数,或方法要使用的参数等),要考虑保存至内部的对象的状态可能在外部发生变化。此时可以进行防御性拷贝,将外部对象..
  • 第181页
    Item38:检测参数的合法性 一般希望越早发现错误越好,因此希望能在方法入口处检测参数的合法性。 对于公开的方法,要使用if语义检测参数并抛出相应的异常,最好再使用javadoc进行说明;对于私有的方法,可以使用a...
  • 第179页
    Item37:使用标记接口来定义类型 标记接口是指没有定义任何方法的接口。这对于设计者来说相当于标记了某个类型,为其赋予某种含义。 标记接口相对于注释的优势是,注释一旦申明,有可能就会被用于所有的类和接口中...
  • 第176页
    Item36:使用Override注释 使用Override注释可以防止未重写以为重写了的方法。从java1.6以后,Override也能使用在实现接口的方法上。 虽然对于具体类来说,是否实现接口或抽象类不必一定要使用Override,因为编译..
  • 第169页
    Item35:使用注释而非成员命名空间 成员命名空间是指使用固定规则对成员进行命名后,其它对象会根据其命名进行特定的行为。如将方法命名为test开头则能被JUnit运行为测试方法。 在1.5之后应当使用注释的方式标明成...
  • 第168页
    Item34:使用基于接口的扩展Enum 由于Enum不能被继承,因为继承后的enum实例逻辑关系会很复杂:子类实例是任何一个父类的实例,但父类的却不是子类的实例。 因此当需要扩展某个enum时,可以让其继承某个接口。其它...
  • 第161页
    Item33:使用EnumMap来代替基于ordinal的Map 因为当enum中的实例发生变化时,会影响原来map的大小,当使用array来实现此类map时可能会产生exception。
  • 第159页
    Item32:使用EnumSet来代替int的bit集合
  • 第158页
    Item31:不要使用Enum中的ordinal 因为一旦申明实例的顺序发生变化,则ordinal的值也会发生改变。 解决方法是显式定义一个成员变量指明enum实例的值。
  • 第147页
    Item30:enum类型 enum类型在Java中被视为静态类,其中的实例是final的,且没有对外暴露的构造函数。实现了Comparable和Serializable。 可以在enum类型中申明和定义final字段、方法及构造函数(在定义实例时调用)。...
  • 第142页
    Item29:使用Class<?>来实现泛型的类型异构的集合 如: public <T> void putFavorite(Class<T> type, T instance) { if (type == null) throw new NullPointerException("Ty...
  • 第134页
    Item28:使用有界线的通配泛型以增加API的灵活性 普通的泛型类T中的泛型方法,只支持和当前类型相同的类型,因为泛型不支持协变,所以这些方法都只能接受恰好为T的类型。 可以通过? extends T,和? super T来进行..
  • 第129页
    Item26,27:使用泛型类和泛型方法
  • 第119页
    Item25:使用List而非Array 1. Array是协变的,而List不是。即如果T1是T2的子类,那些T1[]也是T2[]的子类,但会在运行时检测对象的真实类型;但List<T1>则不是List<T2>的子类。协变在一些条件下会产生..
  • 第116页
    Item24:消除泛型unchecked warnings
  • 第109页
    Item23:尽量使用泛型类型 Set 是Raw Type,Set<Object>是Object的集合,Set<?>是未知类型的集合。后两者是类型安全的。
  • 第106页
    Item22:关于嵌套类 如果嵌套类和外部类没有引用关系,嵌套类可以独立于外部类而存在,那么应当申明为静态嵌套类。 静态嵌套类不持有外部对象的引用,所以不能访问外部对象的非静态成员;内部类持有对外部对象的...
  • 第103页
    Item21:使用函数对象来表示策略 即将行为封装在统一接口的对象内,以达到实时替换产生不同行为的目的。 虽然接口强制方法为public的,但只要将此策略类型申明为嵌套类,即可防止将接口暴露给外部。 当策略对象只...
  • 第100页
    Item20:不要使用标记类而宁愿使用继承层次 标记类是指一个类的行为由其中的某个标记位决定。 1. 标记类中会存在其它不属于其对象的字段,会影响类的职责划分 2. 标记类不便于修改,增加一种新的情况时需要对每一...
  • 第98页
    Item19:使用接口时仅定义类型,而不要定义常数
  • 第93页
    Item18:接口优于抽象类 区别主要在于:接口不能有实现;继承了抽象类将不能再继承其它类 接口便于实现mixin功能, 即在主要功能中加入其它的辅助功能,如Comparable等 接口可以多重继承,便于实现非严格的层级结...
  • 第87页
    Item17:为可继承的类进行文档说明 说明哪些公开或可调用的方法引用了哪些可被继承重写的方法。以便其它人在继承此类时注意重写所造成的后果。 其中特别需要注意,构造函数中不要调用可被重写的方法,否则可能会造...
  • 第81页
    Item16:组合优于继承 因为继承后的子类依赖于其父类的行为,将会打破封装性。由此将暴露父类的行为,且不能修改。并且当父类的行为依赖于父类中其它可被重写的行为,那么子类的重写将有可能产生预期之外的其它行为...
  • 第73页
    Item15:最小化类的可变性 实现方法: 1. 使类无法被继承 //使用final,或私有构造器,并提供静态方法来提供对象 2. 不公开改变对象状态的方法 3. 使用final成员 4. 使用private成员 5 尽可能少地引用可变类..
  • 第71页
    Item14:对公共的类,使用方法访问字段 但对于包内可见或内部私有类,则可以直接访问字段。 虽然公开final的成员所产生的影响要小,但仍然会导致这个字段的永远公开和无法改变。
  • 第67页
    Item13:最小化类和成员的可见性 对于顶层类,只有两种可见性:default和public。所有public的类将成为API的一部分,将难以改变;default的类只属于API实现的一部分。
  • 第64页
    Item12:关于Comparable 也需要满足自反性、对称性、传递性。但与Equals不同,遇到类型不相符的对象可以直接抛出Exception。 Comparable==0的结果不一定要和Equals保持一致,但会造成一些奇怪的现象。因为普通的Co...
  • 第60页
    Item11:关于clone() 只有对于实现了Cloneable接口的对象,Object.clone()才会工作,否则将抛出Exception。Object.clone()不经过构造函数,只是单纯的字段对字段的复制。对于引用对象,将复制引用同一个对象。对于d...
  • 第52页
    Item10:重写ToString ToString的完整语义应当是返回人可读的完整而精确描述对象的字符串。 对于值对象,可以指定返回串的格式,以便其他人解析,但会存在格式不可变的缺陷。 若不指定格式,需要确保将每个有意义...
  • 第45页
    Item9:对于重写Equals的类型要重写hashCode方法 hashCode必须ThreadSafe。Equal的对象必须有相同的HashCode,但有相等HashCode的对象不一定需要Equal;不Equal的对象不一定要有不同的HashCode,但为其分配不同的Ha...
  • 第35页
    Item8:如何实现Equals 对于父类和增加了字段的子类之间,可能存在违反“对称性”的情况。 应当注意这类情况的发生,可以使用组合来规避这种情况。 一般情况下,Equals的实现: 1. 判断是否是同一个对象 2. ..
  • 第27页
    Item7:避免引用Finalizer 因为无法确定对象会被在何时回收,因此非托管资源需要手动明确地回收。 使用显式的方法释放资源。
  • 第24页
    Item6:避免保留废弃的引用 对于需要自己维护内存的对象,应注意将废弃的引用设为null以便垃圾回收。 对于普通程序而言,应让对象超过其作用域以被垃圾回收,不需要显示设为null。 常见的内存泄漏有:未被null..
  • 第21页
    Item5:避免创建重量级的重复对象 实现方法:将可重用的重量级重复对象提升其作用域。 缺点:若提升级静态级,但又没有访问,可能造成内存浪费。但不要试图使用延迟加载等方法,一方面会加大代码的复杂度,另一方..
  • 第19页
    Item4:使用私有构造器来保证无法实例化 实现方法:显式申明构造函数以覆盖默认的public无参构造器;并在内部抛出Error以保证无法通过反射调用
  • 第17页
    Item3:使用Enum类型来实现Singleton 优点:能避免处理序列化时产生的问题
  • 第11页
    Item2:当构造方法中的参数有很多时,使用Builder。 实现方法: 将Builder作为当前类的一个静态类;在当前类的构造方法中以Builder作为参数,并对属性一一赋值;若必填属性缺失时,可抛出错误 优点: 1. 避免了..
  • 第5页
    Item1:使用静态方法构造对象 优点: 1. 相比于构造函数而言可以有不同名称,赋予不同的语义便于理解 2. 对构造函数进行封装,包装更多行为,如返回同一个对象等 3. 相比于构造函数,静态方法可以返回子类及不同..

CLR via C# (50) 更多

  • 第520页
    超过85000字节的对象被视为大对象,直接被放到第2代。 若频繁生成大对象,将导致第2代被频繁回收,降低效率。
  • 第507页
    由于大部分程序的根都主要存在于线程栈上,因此避免太深的栈能加快垃圾回收的扫描。 一个方法是避免使用递归。
  • 第503页
    为垃圾回收分代是一种优化,它做出如下假设: 1. 对象越新,生存周期越短 2. 对象越旧,生存周期越长 3. 回收部分堆比回收整个堆效率更高 默认情况下,0代的大小为256K,能放入CPU的L2缓存中,因此速度很快。 ...
  • 第487页
    实现IDisposable.Dispose()方法有责任完成下面的任务: 1、感知所有的非托管资源。 2、感知所有的托管资源(包括卸载一些事件)。 3、设置一个安全的标记来标识对象已经被处理。如果在已经处理过的对象上调用任何方...
  • 第462页
    相比于C语言的运行时堆,托管堆将对象连续地分配在内存中,而非在空余处插入对象。这样将使用CPU的Cache性达到更好的水平,从而提升访问速度。 在垃圾回收时,静态字段、方法参数、栈上的局部变量及CPU寄存器中指向...
  • 第370页
    C#中关于委托的语法糖: 完整形式: new 委托类型(对象.方法名); 1.自动推断委托类型: 由于不同名称的委托类型只要引用相同签名的方法就可以接受相同的方法的实例,因此可以根据传入的方法的签名推断出所有符合要...
  • 第359页
    使用delegate关键字申明一个委托类型,每个委托类型引用一个方法,其返回值与参数在申明委托类型时指定。 编译器会将此申明转化为继承自MulticaseDelegate的class,其又继承自Delegate。由于delegate的本质是class..
  • 第348页
    对于1维0基数组,编译器在生成代码时,会自动优化for循环中a.Length的属性,替换为临时变量而不会每次去调用。并且会在for循环前检察元素是否都在数组范围内,这样在循环的过程中可以省去大量的if判断。 因此,1维0...
  • 第344页
    申明某类型的数组时,CLR会创建此类型。其继承自Array,并实现了IEnum,IList及ICollection的非泛型版接口。 对于1维0基数组,CLR自动为其及其父类实现泛型版的上述接口;但当数组为值类型时,不会为其父类实现泛型...
  • 第341页
    对于数组的类型转换,转换的数组必须具有相同的维度。对于数组类型的隐式转换,需要类型之间必须存在正确的隐式转换;也可以直接对数组进行显式转换,但在运行时失败会抛出exception。 对于值类型数组,不能进行类..
  • 第338页
    尽量使用1维0基数组,因为CLR对于0基数组进行了大量优化,虽然也支持非0基数组。 对于1维数组,IL中有特殊的指令以加快其效率。
  • 第647页
    Task的Wait方法将等待任务直至执行完成。 当Task已经在运行时,当前线程将会阻塞;当Task没有运行时,当前线程会主动执行Task当在执行完成后返回。 这样的好处是若Task没有开始,则不用产生一个新的线程去替代当前...
  • 第311页
    ToString(string format, IFormatProvider provider) 此方法中的format指示了输出格式的pattern,IFormatProvider 则能提供解释此pattern的format。 C#中的CultureInfo是IFormatProvider 的常用实现。若provider为...
  • 第294页
    比较string时,建议使用bool Equals(string, CompareOptions)方法,以显式地指明使用的比较方式:Ordinal,CurrentCulture。前者用于程序内部字符串的比较和排序,忽略任何文化特性,能加速字符串的比较;后者用于向...
  • 第291页
    可以使用Environment.NewLine来产生换行符,此方式通过获取每个平台各自的换行符以满足在各个平台上的可运行性。
  • 第273页
    显式实现一个接口中定义的方法的模式,是明确使用 接口名.方法名 的方式指明实现的是接口中定义的哪个方法,且不能指定可访问性(因为强制是public)。在调用时必须转换为接口进行,因此也不能被派生类使用base.的方...
  • 第270页
    CLR需要接口方法为virtual,因此接口方法将默认为virtual sealed以防止被重写,若显式申明为virtual则不为sealed,可以动态绑定。 将对象转换为接口类型进行调用时,会以对象的真实类型所具有的接口方法进行调用。..
  • 第255页
    不同类型参数的泛型类型不能相互转换。除非为类型参数标明协变和逆变。 in TArg 表示TArg有逆变性,能接受其派生类型作为类型参数;out TResult表示TResult有协变性,能接受其基类类型作为类型参数。 判断泛型接口...
  • 第251页
    对于引用类型实参的封闭泛型类型,CLR将共享生成的代码,因为所有引用类型均能视为堆上的指针;但对于值类型实参的泛型类型则需要生成各自的泛型代码,因为值类型的大小是可变的。 对于同一个AppDomain下的程序集,...
  • 第248页
    不允许对开放的泛型类型实例化,即需要填写所有的类型参数。 类型参数不同的同一个泛型类型,在类型对象中有各自的静态数据字段,因此有各自的静态变量成员,静态构造器也会被各自执行。因此可以使用静态构造器来实...
  • 第236页
    申请事件时,使用public event 委托类型 事件名 的方式,其中委托类型一般为EventHandler<EventArgs>。 其它类型在内部申明符合事件委托类型的方法创建委托的实例并加入到事件中。 注册了事件的对象由于被..
  • 第211页
    自动属性AIP的缺点如下: 1. 暂不支持字段的初始化,需要在每个构造函数中初始化。 2. 使用了AIP的类型不能被反序列化。因为自动生成的字段名根据编译器的不同可能不同,在每次编译时也可能不同。 3. 调试时不能在...
  • 第204页
    方法的参数应尽可能的抽象,使用接口、避免实体类,因为这样可以让调用者选择传入什么类型的实参。 方法的返回值应尽可能的具体,尽可能的使用实体类,因为这样可以让调用者选择将返回值视为基类、接口、或真实的实...
  • 第796页
    out和ref都会使用传引用的方式进行参数的传递。 但ref则指明了参数一定由方法调用者进行初始化,调用方必须初始化参数,被调用者可以在方法内部读取/写入值;out则表明使用的参数不一定进行了初始化,在方法内部不..
  • 第185页
    扩展方法的优点是增加代码的可读性和可维护性,并使静态方法所在的类名透明化。 缺点是不易于版本管理,若被扩展的对象又增加了和扩展方法同样名称的方法,那么在绑定时会优先绑定非扩展的方法,导致代码行为在不知...
  • 第182页
    CLR允许方法名称和参数类型相同但返回值不同的多个方法同时存在,但大部分语言包括C#等都没有利用这一点,不支持仅返回值不同的方法。通过IL可以实现,但IL不应写出这样的代码,因为这类方法将不能被其它语言所调用..
  • 第169页
    值类型的构造器将永远不会被编译器主动调用。 甚至可以没有构造器,包括默认构造器(因为值类型不允许有无参的构造函数)。 若没有定义构造器,则无法直接使用inline的初始化方法。 由于值类型的所有字段均要在定...
  • 第167页
    编译器会对每个inline初始化的字段生成代码,并插入到每个构造函数的最开始。 再插入基类构造函数(如果没有显式调用的话),最后执行构造函数本身的代码。
  • 第166页
    不要在构造器中调用会影响对象构造的虚方法。 派生类会重写虚方法,在构造对象时先进行基类的构造,此时基类调用虚方法时,由于真实对象为派生类型,因为会调用派生类的虚方法,但此时派生类仍在构造中,因此会产生...
  • 第160页
    常量只能为元数据类型,其它类型作为常量时只能将其设为null。 常量会在编译为IL时被替换为真实的值,因此常量没有引用,没有地址。引用常量的其它程序集会将常量的值改为实际值,因此在更改常量值以后,需要对引用...
  • 第150页
    对于方法调用,C#编译器将代码编译成IL代码时,使用call来调用静态方法,使用callvir来调用虚和非虚的实例方法。 call指令假定调用的对象不为null,但并不会进行检查,通过非虚的方式,通过对象调用时申明的类型的..
  • 第143页
    对于类型中的成员,有以下几种可访问性: 1. private(Private) 仅允许定义类型、嵌套类型中的方法访问 2. protected(Family) 在private的基础上还允许任意程序集中的派生类中的方法访问 3. internal(Assembly) 在...
  • 第140页
    文件级别的类的可见性只有public internal。 public表示在其它程序集中可见,internal表示仅在程序集内部可见。 可以将其它程序集申明为本程序集的友元,以便其能访问internal的类型而对其它程序集仍不可见。
  • 第128页
    同一性,即两个对象是同一个对象。要使用referenceEquals方法来判断而不能使用==,因为可能对其进行过操作符重载。 相等性,即两个对象内容相同。要按以下步骤实现: 1 如果obj为空,则FALSE 2 如果this 与obj同一,...
  • 第115页
    装箱时会将在栈上的值类型的内部字段复制到堆中,并加上类型对象指针和同步块索引。 拆箱时仅进行装箱内容的指针查找,但若要进行赋值给值对象,则会将堆中的内容复制到栈上。 装箱后的对象与原对象是两个对象。
  • 第110页
    值类型并没有指针,变量中包含了实例本身的字段,且不受垃圾回收器的控制。 结构和枚举都属于值类型。 所有结构都由ValueTpye派生,ValueTpye由object派生; 所有枚举由Enum派生,Enum由ValueTpye派生。 要将类型定义...
  • 第105页
    checked unchecked用于标明是否打开溢出检查,C#默认关闭。 对于checked块中调用的方法,则没有用处,需要在方法内部检查。
  • 第98页
    调用静态方法时,直接定位到对应类型的类型对象,调用方法表中的方法。 调用非虚方法时,定位到对象申明类型的类型对象,查找方法,若无此方法,则回溯基类类型对象进行查找。 调用虚方法时,则先要找到发出调用的对...
  • 第97页
    实例化对象前,需要加载类型对象,包含类型对象指针,同步索引块,静态字段及方法表,及指向基类类型对象的指针。类型对象的类型对象指针指向Type类型的特殊类型对象。 实例化对象时,对象中包含类型对象的指针(指向...
  • 第9页
    一个程序集可以包含不同命名空间的类型,一个命名空间的类型也能在多个程序集中实现
  • 第87页
    is用于判断对象是否和某类型兼容,返回bool,常先用is检查后再cast对象。但这会导致2次CLR的类型检查。 as相当于之前的简便形式,并且只进行一次类型检查,返回null或转换后的对象。
  • 第72页
    在GAC中安装程序集能使程序集被多个应用程序共享,从而减少总体内存占用,并可以很容易将新版本部署到GAC中让其它程序通过一个发布者策略使用这个新版本。 然而只有管理员才能向GAC中安装程序集,并且违反简单的复制...
  • 第65页
    为了区分不同程序的相同文件名的文件,ms采用强命名程序集。即使用文件名+版本号+语言标识+公钥标记 对程序集进行区分。公钥标记是公钥的sha 1哈希。 强命名程序集可以私有化部署,也能全局部署在其它已知位置。
  • 第45页
    程序执行首次需要某个类型时,CLR会先加载含有清单的文件,查找所在的文件,加载并内部登记。 因此并非在一开始就加载所有程序集的文件,并不要求被引用的程序集文件全部存在。
  • 第40页
    程序集是最小可复用单位。在逻辑上可视为一个exe或dll,但在物理上可能分散为多个文件。以便于区分逻辑表示和物理表示,达到良好的需求空间性能分配。 如一部分类型可以放在另一个存在于网络中的文件上,只能当需要..
  • 第25页
    由CTS,common type system,作为标准,CLR则贯彻了这些规则,所有面向CLR的语言在编译后都形成符合规范的IL以被CLR理解和编译。 然而,不同语言的特性差异巨大,因此ms提出了CLS以定义所有语言最小的公共功能集。若...
  • 第17页
    由于IL更容易被反编译,因此可能产生产权保护问题。但大部分程序部署在web,因此IL无法被拿到。也能使用混淆器对源代码的符号进行打乱。
  • 第12页
    执行程序的流程: 1 先检测代码引用的所有类型,进行加载并分配内在空间记录结构。 2 对于第一次执行的方法,JITcompiler将IL代码编译为本地CPU指令。 3 指令保存至进程内存中,并修改clr结构中对此方法的执行引用,...
  • 第11页
    允许不在同语言之间切换 同时又紧密集成,是CLR的一个重要特点,因此能支持混合语言编程以发挥不同语言的特性!
  • 第4页
    不同托管语言的编译器总是生成托管模块(包括IL中间语言和元数据),再由CLR在运行时编译为本地语言。
<前页 1 2 3 后页>