C#学习笔记(八)C#的一些设计技巧

    技术2022-05-11  72

    编码习惯

    1.命名规范,接口用I开头做前缀,异常类使用Exception作为后缀。内部成员变量用Camel命名法。小写开关,每单词首字母大写。2.使用有意义的变量名称和名称空间。有返回值的方法形如GetMyObjectState()。3.所有的成员变量都应该声明在顶部,同时使用一个空行来将它们和属性、方法分开。4.总是将大括号放在一个新行上。

    委托再议

    定义委托实际上是定义一个“类型”的委托,不是一个具体的实例。委托类型指定它代表的方法的返回类型和参数列表。它代表具有相同参数列表和返回类型的任何方法。

    <modifiers>delegate <return_type><delegate_name>(argument_list)-->public delegate bool ProcessAnything(double d);

    创建委托实例,new关键字。ProcessAnything pa = new ProcessAnything(account.WithDraw);括号里面是实例方法,此方法必须和代理声明时的返回类型和参数列表相同。

    委托的调用时通过输入委托实例的名称和要传递给委托所表示的方法的参数。

     

    Equals

    考虑覆写Equals(object obj)。.NET提供了默认的实现方法(引用指向同一对象),.NET将在比较和查询时使用这个方法,实现自己比较的“相等”定义,就需要覆写此方法。例如,两个客户名称或代码相同,我们就认为对象是相同的。对.NET来说,如果new了两次就认为是不同的。这里需要覆写。如:

    public class BankCustomer{

        public string FirstName;    public string LastName;    //……

    public override bool Equals(object obj){    if (obj==null)        return false;    if ((obj.GetType().Equals(this.GetType())) == false)         return false;    BankCustomer other;    other = (BankCustomer)obj;    return this.FirstName.Equals(other.FirstName) && this.LastName.Equals(other.LastName);

    }

    }

    要求:Equals必须是自反的(自己比较自己必须返回True)。必须是对称的(X Equals Y则 Y Equals X)。必须是可以传递的,(即X Equals Y ,Y Equals Z,则X Equals Z。)必须是一致的,如果被比较的值没有变化,则始终应返回同一结果。

    如果覆写了Equals,也需要覆写GetHashCode。(不覆写的情况下编译器会提出警告)。这是因为如果两个对象Equals,GHC必须返回相同的值。可根据Equals字段来覆写GHC。

    public override int GetHashCode(){    return this.FirstName.GetHashCode() + this.LastName.GetHashCode();

    }

    HashTable提供高效的搜索,基于(Key,Value)pairs(键/值)对-键必须是唯一的,可通过搜索Key来查找。

     

    Clone

    如果要实现克隆功能,就要实现ICloneable接口。实现clone方法。需要确定是“浅表复制”还是“深复制”。浅复制(shallow)复制顶级对象;深复制(deep)是复制对象和子对象。

    return new BankCustomer(...);相当于return this.MemberwiseClone();

    Close & Dispose

    实现IDisposable。一些对象需要清理。如果类中“抓住”资源,应该重新设计类,实现Dispose & Close方法。

     

    XML文档索引

    使用XML注释,自动完成class-level文档。例如:

    ///<summary>///说明……///</summary>///<param name = "amt"> 参数说明</param>///<exception cref = "System.Exception"> 异常抛出说明</exception>

    String相关知识

    string是不可变的对象。字符串操作并不更改当前字符串,而是创建并返回新的字符串,速度慢。

    要频繁进行字符串连接操作时,可使用StringBuilder类来发送性能。连接操作越频繁,差别越明显。

    字符串驻留如果生成新的字符串时会查找系统内在中是否有相应的字符串,如果找到就指向该内在。节省内存空间。使用Intern关键字(可查找相关资料)。

     

    委托的概念及定义

    用特定的签名(即返回值类型和参数列表)来封装方法。一个委托的实例可以用来封装一个静态或实例的方法。是类型安全的。

    (MSDN Microsoft)

    委托是一个回调功能,但更智能,它定义了非常严格的参数,使之可以在类的服务端和客户端传递。(CodeProject)

    委托是一种引用方法的类型,一旦分配了方法,将与该方法具有完全相同的行为。委托方法的使用可以像其它任何方法一样具有参数和返回值。(C#编程指南)

    增加一层间接层来实现晚绑定,从而获得更为松散的耦合。

    一个委托可以一次搭载多个方法,而不是一次一个。当我们唤起一个搭载了多个方法的委托时,所有方法以其被搭载到delegate object的顺序被依次唤起。

    实际上是创建了Delegate类或MulticastDelegate类,提供一组方法用以询访委托对象或其搭载的方法。

    委托是函数的封装,代表一“类”函数,符合一定的签名。同时,也可以看成函数的抽象,是函数的“类”,此时,委托的实例代表一个具体的函数。

     

     

    为什么使用委托

    1)更加灵活的方法调用。2)用于异步回调

        由于实例化委托是一个对象,所以可将其作为参数进行传递,也可以将其赋值给属性。这样方法便可以将一个委托作为参数来接受,并且以后可以调用该委托。这称为异步回调,是在较长的进程完成后用来通知调用方的常用方法。以这种方式使用委托时,使用委托的代码无需了解有关所有方法的实现方面的任何信息。如:

    public void MethodWithCallback(int parm1,int parm2, Del callback)

    {    callback("The Number is:" +     (parm1+parm2).ToString());}

    回调的另一个常见方法是定义自定义的比较方法并将该委托传递给排序方法。

     

    3)多线程编程中使用委托来指定启动一个线程时调用的方法。4)用于C#中的事件模型。用它们指明处理给定事件的方法。

     

    如何使用委托

    先声明,再实例化并指明所代具体方法。

    何时委托,何时接口?使用委托建议1)使用事件设计模式时2)封装静态方法可取时3)当调用方不需要访问实现该方法的对象中其他属性、方法或接口时4)需要方便的组合5)当类可能需要该方法的多个实现时。使用接口建议1)当存在一组可能被调用的相关方法时。2)当类只需要方法的单个实现时。3)当使用接口的类想要将该接口强制转换为其他接口或类类型时。

     

    多播委托应用于事件模型。

    代理相加。Button.Click+=...

     


    最新回复(0)