(8)合式类型

 

*重写object的成员

*重写ToString()

        int intNuma = 1;
        int intNumb = 2; 
        public override string ToString()
        {
            return string.Format("{0} {1}",intNuma,intNumb);
        }

*重写GetHashCode()   [不熟悉]

如果想要重写Equals(),就应该重写GetHashCode(),如果忘记这样做,会显示一条警告信息。

在将类作为散列表集合的键(key)使用时,最好也将GetHashCode()重写。

散列码(hash code)的作用是生成与对象的值相对应的一个数字,从而高效的平衡一个散列表。

想要获得一个良好的GetHashCode()实现,可以参照一下必须:

必须:相等的对象必然有相等的散列码。(若a.Equals(b),则a.GetHashCode()==b.GetHashCode())

必须:针对一个特定的对象,在这个对象的生存期内,GetHashCode()始终返回相同的值,即使对象的数据发生了改变。【缓存方法的返回值,从而确保这一点】

必须:GetHashCode()不应该发生任何异常,总是成功返回一个值。

性能:散列码应尽量可能保持唯一。

性能:可能的散列码应该在int的范围内平均。

性能:GetHashCode() 的性能应该优化。

……

    public  class Longitude
    {
    }
    public class Latutide
    {
    }
    public struct Coordinate
    {
        public Coordinate(Longitude longitude, Latutide latutide)
        {
            _Longitude = longitude;
            _Latutide = latutide;
        }

        public Longitude Longitude { get { return _Longitude; } }
        private readonly Longitude _Longitude;

        public Latutide Latutide { get { return _Latutide; } }
        private readonly Latutide _Latutide;

        public override int  GetHashCode()
        {
 	        int hashCode =Longitude.GetHashCode();
            //as long as the hash codes are not equal
            if (Longitude.GetHashCode()!=Latutide.GetHashCode())
            {
                hashCode^=Latutide.GetHashCode();//or 
            }
            return hashCode;//假如基类不是Object,那么应该在XOR运算总包含base.GetHashCode().
        }


*重写Equals()

重写Equals()而不重写GetHashCode()会出现一个警告。

“对象同一性”和“相等的对象值” :相等的值类型,相等的引用类型,同一(相等的引用)

值类型本身不可能引用相等。

相等性实现的指导原则

Equals(),==,!=运算符应该一起实现。

一个类型的Equals(),== ,!=实现中应该使用相同的算法。

实现Equals(),==,!= 时,也应该实现一个类型的GetHashCode()方法

GetHashCode(),Equals(),==,!=永远不能引发异常。

实现IComparable时,与相等性有关的方法也要实现。

    public  class Longitude
    {//……
    }
    public class Latutide
    {//……
    }
    public struct Coordinate
    {
        public Coordinate(Longitude longitude, Latutide latutide)
        {
            _Longitude = longitude;
            _Latutide = latutide;
        }

        public Longitude Longitude { get { return _Longitude; } }
        private readonly Longitude _Longitude;

        public Latutide Latutide { get { return _Latutide; } }
        private readonly Latutide _Latutide;

        public override bool Equals(object obj)
        {
            //1.check for null 
            if (obj == null)
            {
                return false;
            }

            //3.equivalent data types
            if (this.GetType() != obj.GetType())
            {
                return false;
            }
            return base.Equals((Coordinate)obj);
        }
        public bool Equals(Coordinate obj)
        {
            //1:Check for null  if a reference type
            //if (obj == null)
            //{
            //    return false;
           // }
            //2:checke for ReferenceEquals if this is a reference type
            // if (ReferenceEquals(this, obj))
            //{
            //  return ture;
            // }
            //
            //4:Possibly check  for equivalent hash coeds
           // if (this.GetHashCode() != obj.GetHashCode())
           // {
           //    return  false;
           // }

            //5.check base.equals if base override equals
           // System.Diagnostics.Debug.Assert(
          //      base.GetType()!=typeof(object));
          //  if(!base.Equals(obj ))
          //  {
          //      return false ;
          //  }

            //6:compare identifying fields for queality using an overload of Equals on Longitude
            return ((Longitude.Equals(obj.Longitude))&&(Latutide.Equals(obj)));
  
        }

        //7.override GetHashCode()
        public override int  GetHashCode()
        {
 	        int hashCode =Longitude.GetHashCode();
            //as long as the hash codes are not equal
            if (Longitude.GetHashCode()!=Latutide.GetHashCode())
            {
                hashCode^=Latutide.GetHashCode();//or 
            }
            return hashCode;//假如基类不是Object,那么应该在XOR运算总包含base.GetHashCode().
        }

*运算符重载(operator  overloading):x.y f(x) new typeof default checked unchecked delegate is as = =>.其中,=作为赋值运算符,是不能实现重载的。

        public static bool operator ==(Coordinate leftHandSide , Coordinate rightHandSide)
    {
        if (ReferenceEquals(leftHandSide, null))
        {
            return ReferenceEquals(rightHandSide, null);
        }
        return ReferenceEquals(leftHandSide,rightHandSide);
    }

        public static bool operator !=(Coordinate leftHandSide,Coordinate RightHandSide)
        {
            return !(leftHandSide == RightHandSide);
        }


*二元运算符:重载成二元static方法,其中这少有一个参数的类型的是包容类型(当前正在重载该元素的类型)。

 public struct Arc
    {
        public Arc(Longitude arclongitude, Latutide arclatutide)
        {
            _arcLongitude = arclongitude;
            _arcLatutide = arclatutide;
        }

        public Longitude arcLongitude { get { return _arcLongitude; } }
        private readonly Longitude _arcLongitude;

        public Latutide arcLatutide { get { return _arcLatutide; } }
        private readonly Latutide _arcLatutide;
    }

    public struct Coordinate
    {
        //...
        public static Coordinate operator +(Coordinate source, Arc arc)
        {
            Coordinate result = new Coordinate(new Longitude(source.Longitude + arc.arcLongitude),new Latutide(source.Latutide+arc.arcLatutide));
            return result;
        }                                                                                                                                                                                                                         }//其中,也需要实现Longitude和Latutide中+的实现。

*一元运算符

类似二元运算符,只获取一个参数,该参数也要是包容类型(正在重载运算符的类型)

*重载true和false

public static bool operator false (IsValid item)

public static bool operator true( IsValid item)
***转型运算符():定义转型运算符在形式上类似于定义其他运算符,只要用"operator"替换待转换结果类型。另外,operator关键字后面要跟表示隐式或显示转换的implicit 或explicit。  一般会引发异常的转换都应该是显示的。

    public class Latitude
    {//……

         public Latitude(double decimalDegress)
       {
           _DecimalDegress=decimalDegress;
       }

        public  double DecimalDegress
        {
            get 
            {
                return _DecimalDegress;
            }
        }
        private readonly double _DecimalDegress;
        //...

        public static implicit operator double(Latitude latitude)
        {
            return latitude.DecimalDegress;
        }

        public static implicit operator Latitude(double degress)
        {
            return new Latitude(degress);
        }
    }


**更改程序集目标

为了将A.cs,B.cs,C.cs编译成类库

> csc /target:library /out:ABC.dll A.cs B.cs C.cs

 **引用程序集

C#允许开发者在命令行上引用程序集。具体的选项是/reference(/r缩写),后跟一个引用列表。

csc.exe /R:ABC.dll program.cs 

**类型封装

默认情况下,没有任何访问修饰符的类会被定义成internal ,结果是该类无法从程序集的外部访问。C#为类提供的访问修饰符有public和internal。

public :凡是能访问类型的地方,都能访问成员。如果类是internal 的,则成员只在内部可见。如果包容类是public的,public成员就可以从程序集的外部访问。

internal :成员只能从当前程序集中访问。

private

protected:成员可以从包容类以及派生的任何子类中访问,不管程序集是哪个。

protected internal:成员可以从包容程序集内的任何地方访问,并且可以从包容类型的任何派生类中访问,即使派生类在一个不同的程序集中。

*定义命名空间:namespace,可以嵌套。

*XML注释:单行///    多行/**    */

*生成XML文档文件: >csc /doc:Comments.xml DataStorage.cs

*垃圾回收:只处理引用对象,回收堆上的内存。

**弱引用:弱引用不会禁止对一个对象执行垃圾回收,但是他们会维持一个引用。如果你认为一个对象(挥着对象集合)应该进行弱引用,需要把它赋给System.WeakReference.(如同操作系统中,为多次被访问的数据而设置的高速缓存区)

        private WeakReference Data;
        public FileStream GetData()
        {
            //获取当前System.WeakReference对象应用的对象
            FileStream data = (FileStream)Data.Target;
            if (data != null)
            {
                return data;
            }
            else
            {
                //load data
                //...
                //create a weak reference to data for use later;
                Data.Target = data;
            }
            return data;
        }


*资源清理:它并不是用来清理文件句柄,数据库连接字符串,端口或者其他有限资源的。

*终结器(finalizer)允许程序员编写代码来清理一个类的资源。

//没有参数,没有返回值,没有访问修饰符。

~className()

{

     Close();

}

public void Close()

{

if(Stream!=null)

Stream.Close();

}

if(File!=null)

{

File.Delete();

}

*使用using语句进行确定性终结。

在using语句中,可以实例化多个变量,只要用逗号分割,变量需要是相同的类型,而且都实现了IDisposable().为了强制使用相同的类型,数据类型只能指定一次,而不是在每个变量声明之前都指定一次。

    class TemporaryFileSystem : IDisposable
    {
        public TemporaryFileSystem()
        {
            _File = new FileInfo(Path.GetTempFileName());
            _Stream = new FileStream(File.FullName,FileMode.OpenOrCreate,FileAccess.ReadWrite);
         }
        ~TemporaryFileSystem()
        {
            Close();
        }
        public void Close()
        {
            if (Stream != null)
            {
                Stream.Close();
            }
            if(File!=null)
            {
                File.Delete();
            }
            System.GC.SuppressFinalize(this);
        }

        public void Dispose()
        {
            Close();
        }    

        public FileStream Stream
        { get
            {
                return _Stream;
            }
        }
        private readonly FileStream _Stream;

        public FileInfo File
        {
            get
            {
                return _File;
            }
        }
        private readonly FileInfo _File;
    }
        static void search()
        {
            TemporaryFileSystem fileStream = new TemporaryFileSystem();
            //use temporary file stream;
            //...
            fileStream.Dispose();
            //....
            //在实例化TemporaryFileSystem之后,并在调用Dispose()之前,有可能发生一个异常。
            //假如在这个期间发生异常,Dispose()会等不到调用。为避免这个问题,c#提供了一个using语句。
            using (TemporaryFileSystem fileStream1 = new TemporaryFileSystem(),
                fileStream2 = new TemporaryFileSystem())
            {
                //Use Temporary file stream;
            }
        }


*垃圾回收和终结

上述代码中,System.GC.SuppressFinalize(this);从终结队列(f-reachable)队列中移除TemporaryFileStream类实例,f-reachable是一个引用列表,一个对象只有用在它的终结方法得到调用,而且对象引用从f-reachable队列中删除之后,才会真正成为垃圾。

**延迟初始化:将一个对象的初始化延迟到需要这个对象时进行,就称为“推迟初始化”。

例如,将一个对象的实例化放到另一个的属性的get()方法中,只有在调用属性的get访问器的时,才会实例化对象。

***.net 4.0开始,添加了一个新类版主进行推迟初始化。System.lazy<T>.[不理解]

 class DataCache
    {
        //...
        public string FileStreamName { get; set; }
        public DataCache()
        {
            //不理解,程序中也报错
            _FileStream = new Lazy<TemporaryFileStream>(() => new TemporaryFileStream(FileStreamName));
        }

        public TemporaryFileStream FileStream 
        {
            get 
            {
                return _FileStream.Value;
            }
        }
        private Lazy<TemporaryFileStream> _FileStream;
    }


 


 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值