【C#与.NET程序设计】(6)- C#垃圾回收及接口类型
来源:互联网 发布:江宁淳化街道网络问政 编辑:程序博客网 时间:2024/06/06 07:34
垃圾回收GC
.NET的CLR管理着托管堆,所有存在于托管堆上的对象会在“将来的某一时刻”被垃圾回收器自动销毁。因此 C# 里没有 delete 关键字
- 托管资源
由CLR管理,运行于托管堆上。C#的绝大多数对象 - 非托管资源
不由CLR管理,如 Image Socket, StreamWriter, Timer, Tooltip, 文件句柄,GDI资源,数据库连接等
非托管资源需要手动释放:Dispose (推荐方法)和 Finalize(本质是析构函数)
// 托管堆// new 返回的是一个指向托管堆上对象的引用// 也就是说,对象本身在托管堆上,refToMyCar 保存在栈上,是对象的一个引用Car refToMyCar = new Car();
延迟对象实例化
使用泛型类 Lazy<> 使对象的数据只有在使用时才被创建,达到节约资源,缓解GC压力的目的
// 一首歌曲class Song{ public string Artist {get; set;} public string TrackName {get; set;} public string TrackLength {get; set;}}// 播放器上所有歌曲class AllTracks{ private Song[] allSongs = new Song[10000];}// 播放器class MediaPlayer{ private AllTracks allSongs = new AllTracks(); public AllTracks GetAllTracks() { return allSongs; }}// 调用时间接创建了10000个对象MediaPlayer myPlayer = new MediaPlayer();
使用 Lazy<> 修饰 MediaPlayer 的 AllTracks 类
// 使用 Lazy<> 延迟对象// 播放器class MediaPlayer{ private Lazy<AllTracks> allSongs = new Lazy<AllTracks>(); public AllTracks GetAllTracks() { return allSongs.Value; }// 只有在调用函数 GetAllTracks 时,10000个对象才被创建myPlayer.GetAllTracks();
接口
接口就是一组抽象成员的集合,使用关键字 “interface”声明
可以把接口看做是抽象类的升级版:
- 只有派生类才支持由抽象父类定义的成员,而接口更具独立性,所有类都可以用
- 派生类必须实现抽象父类的所有抽象方法,不论实际是否需要;
而接口没这个限制(但如果要用这个接口,就必须实现其所有方法) - 接口更像是一种公共类的声明,只要有类要用就做具体实现
- 接口可以作为输入参数类型,也可作为返回输出类型
// 自定义接口public interface IPointy{ // 只能定义方法 public int numbOfPoints; // 错误,不能有字段 public IPointy() {...} // 错误,不能有构造函数 byte GetNumberOfPoints(){return numbOfPoints;} // 错误,不能提供实现 // 方法是隐式公共、抽象的 byte GetNumberOfPoints(); // 正确 // 可以定义属性 byte Points{get;} // 正确}// 使用该接口// 与类继承不同,一个类可以接受多个接口class Triangle:Shape, IPointy{ // 实现 IPointy 方法 public byte GetNumberOfPoints() { return 3; } // 实现 IPoints 属性 public byte Points { get{return 3;} }}
使用“is”和“as”确定接口是否被支持
如果不确定当前类是否重写了特定接口,可以使用“is”或“as”测试
// 使用 is Triangle triangle = new Triangle();if(triangle is IPointy) ...// 使用 asIPointy itfpt = triangle as IPointy;if(itfpt != null) ...
接口命名冲突
假设多个接口定义了同样名字和输入输出参数的方法,而一个类同时调用了这些接口,就会造成冲突
此时只能通过显式调用来明确接口(但这种方法是隐式私有的)
// 不同接口定义同样的方法public interface IDrawToFrom{ void Draw();}public interface IDrawToMemory{ void Draw();}public interface IDrawToPrinter{ void Draw();}// Octagon 类支持所有接口class Octagon:IDrawToFrom, IDrawToMemory, IDrawToPrinter{ // 按常规方法会导致混乱 public void Draw() {...} // 显式绑定 Draw // 隐式私有,不能提供修饰符(public) void IDrawToFrom.Draw() {...} void IDrawToMemory.Draw() {...} void IDrawToPrinter.Draw() {...}}
接口层次结构
与类的层次结构类似,接口也可以对父接口做继承
// 接口的继承public interface IDrawable{ void Draw();}// IAdvancedDraw 继承了 IDrawable 的 Draw() 方法public interface IAdvancedDraw:IDrawable{ void DrawInBoundingBox();}
可枚举类型构建(IEnumerable)
如果要对自定义类型实现枚举,可以通过 IEnumerable 接口实现
有2种方式:
- 委托请求到 System.Array (实现了枚举)
- 使用 yield 构建迭代器
// 委托请求到 array// 添加枚举接口支持using System.Collections;public class Garage:IEnumerable{ private Car[] carArray = new Car[4]; public Garage() { carArray[0] = new Car(); carArray[1] = new Car(); carArray[2] = new Car(); carArray[3] = new Car(); } public IEnumerator GetEnumerator() { // 返回数组对象的 IEnumerator return carArray.GetEnumerator(); }}// 这样就可以用 foreach 枚举 Garage 里的每个 Car 对象了Garage carLot = new Garage();foreach(Car c in carLot){...}
yield 的方法更灵活,用户甚至可以自定义顺序
// yield 构建迭代器using System.Collections;public class Garage{ private Car[] carArray = new Car[4]; // 迭代器方法 public IEnumerator GetEnumerator() { foreach (Car c in carArray) yield return c; } // 或者 // yield 构建命名迭代器 public IEnumerator GetTheCars(bool RetuenRevesed) { // 逆序 if(RetuenRevesed) { for(int i=carArray.Length; i!=0; i--) yield return carArray[i-1]; } else { //正序 foreach(Car c in carArray) yield return c; } }}
可克隆对象构建(ICloneable)
由于类是引用类型,简单的赋值操作是浅复制,如果要实现深度拷贝,需要实现 ICloneable 接口
// 可克隆接口public class PointDescription{ public string PetName{get; set;} public Guid PointID{get; set;} public PointDescription() { PetName = "No-name"; PointID = Guid.NewGuid(); // 全局唯一标识符 }}public class Point : ICloneable{ ... public PointDescription desc = new PointDescription(); // ICloneable 接口实现 public object Clone() { // MemberwiseClone 浅复制 // 数值类型可以 clone 过来 Point newPoint = (Point)this.MemberwiseClone(); // PointDescription 是引用类型,需要单独实现 PointDescription currentDesc = new PointDescription(); currentDesc.PetName = this.desc.PetName; newPoint.desc = currentDesc; return newPoint; }}
可比较对象的构建(IComparable)
IComparable 接口指定了一种允许一个对象可基于某些特定值进行排序的行为
// 接口定义了一个对象与类似对象的关系public interface IComparable{ int CompareTo(object o);}
自定义类型需要实现 IComparable 接口以支持比较
// 自定义类型的比较public class Car : IComparable{ public int CarID{get; set;} public string PetName{get; set;} ... // IComparable 的实现 int IComparable.CompareTo(object obj) { // 比较 CarID // 方法1 if(obj is Car) { if(this.CarID > temp.CarID) return 1; if(this.CarID < temp.CarID) return -1; else return 0; } // 方法2,因为 Int 类型已实现 IComparable if(obj is Car) return this.CarID.CompareTo(obj.CarID); }}// 排序Car[] myAutos = new Car[4];...Array.Sort(myAutos);
还有一种方式是实现 IComparer 接口,其定义了一个 compare 方法
但一般需要专门实现一个辅助类来实现比较
// 辅助类public class PetNmaeComparer : IComparer{ int IComparer.Compare(object o1, object o2) { if(o1 is Car && o2 is Car) { return String.Compare(o1.PetName, o2.PetName); } }}// 使 Car 类同时支持 PetName 的比较Car[] myAutos = new Car[4];...Array.Sort(myAutos, new PetNmaeComparer());
参考
【1】C#与.NET 4高级程序设计(第5版)
阅读全文
0 0
- 【C#与.NET程序设计】(6)- C#垃圾回收及接口类型
- 【C#与.NET程序设计】(4)- C#类及OOP
- c#学习笔记-.net垃圾回收机制
- C#中的垃圾回收及资源管理器
- C#中的垃圾回收及资源管理器
- Java与C#的垃圾回收机制
- Java与C#的垃圾回收机制
- Java与C#的垃圾回收机制
- Java与C#的垃圾回收机制
- C#垃圾回收与内存管理【转】
- Java与C#的垃圾回收机制
- Java与C#的垃圾回收机制
- C#内存管理与垃圾回收
- Java与C#的垃圾回收机制
- C#垃圾回收
- c#垃圾回收
- c#中的垃圾回收
- 垃圾回收器 C#
- centos7 安装PostgreSQL
- 更改头像 相册/相机
- 初学者的vue笔记
- Oracle 11g exp导出 deferred_segment_creation参数配置
- lucene(五) 中文分词和高亮显示
- 【C#与.NET程序设计】(6)- C#垃圾回收及接口类型
- 源码解读----之-----k_means(被KMeans类调用)
- 706
- 海内外冬季买房有崛起,“望闻问谈”不可少!
- 分支限界法
- Android 屏幕适配:最全面的解决方案
- 论文发表流程及注意事项
- Dubbo的使用及安装
- 这款移动电源不仅支持双向快充,还有type-c数据线功能