270 likes | 369 Views
信息系统开发 (C#). 目标. 理解属性及其不同的类型、实现 理解和使用索引器 实现委托 定义和触发事件. 属性简介. class Employee { private static string _name; private static string _id; static void Main(string[] args) { _name = Console.ReadLine(); _id = Console.ReadLine(); } }. 直接访问字段 不经验证. 属性简介. … Employee emp;
E N D
目标 • 理解属性及其不同的类型、实现 • 理解和使用索引器 • 实现委托 • 定义和触发事件
属性简介 class Employee { private static string _name; private static string _id; static void Main(string[] args) { _name = Console.ReadLine(); _id = Console.ReadLine(); } } • 直接访问字段 • 不经验证
属性简介 • … • Employee emp; • emp.SetId("A1"); • string Department = emp.Get() • … class Employee { private static string _name; private static string _id; public void SetId(value) { // 验证输入长度小于 2 if (_id.Length > 2) _id = value; } public string GetId() { return _id; } } 每次都调用 GetId() 和 SetId() 方法会很繁琐 属性 方法 SetId(Value) 和 GetId() 分别读取和写入职员 ID
属性简介 class Employee { private static string _name; private static string _id; public string Id { get { return _id; } set { // 验证输入长度小于 2 if (_id.Length > 2) _id = value; } } } 读取ID 时调用 将值赋给 ID 时调用
属性类型 读/写属性 [访问修饰符] 数据类型 属性名 { get{ }; set{ }; } 可以赋值和检索值
属性类型 只读属性 [访问修饰符] 数据类型 属性名 { get{ }; } 只能检索值
属性类型 只写属性 [访问修饰符] 数据类型 属性名 { set{ }; } 只能赋值
属性类型 静态属性 [访问修饰符]static 数据类型 属性名 { get{}; set{}; } 只能访问类的静态成员 应用于整个类而不是类的实例
定义和调用属性 class SavingsAccount { // 类字段用于存储帐号、余额和已获利息 private int _accountNumber; private double _balance; private double _interestEarned; // 利率是静态的,因为所有帐户获得的利息相同 private static double _interestRate; // 构造函数初始化类成员 public SavingsAccount(int accountNumber, double balance) { this._accountNumber = accountNumber; this._balance= balance; } // 只读 AccountNumber属性 public int AccountNumber { get { return _accountNumber; } } 只读属性 演示……
定义和调用属性 public double InterestEarned { get { return _interestEarned; } set { // 验证数据 if (value < 0.0) { Console.WriteLine(“利息 不能为负数"); return; } _interestEarned = value; } } static void Main(string[] args) { // 创建 SavingsAccount 的对象 SavingsAccount objSavingsAccount = new SavingsAccount(12345, 5000);; Console.WriteLine("输入到现在为止已获得的利息和利率"); objSavingsAccount.InterestEarned = Int64.Parse(Console.ReadLine()); SavingsAccount.InterestRate = Int64.Parse(Console.ReadLine()); objSavingsAccount.InterestEarned += objSavingsAccount.Balance * SavingsAccount.InterestRate; Console.WriteLine("获得的总利息为: {0}", objSavingsAccount.InterestEarned); } 将设置 InterestEarned属性
定义和调用属性 static void Main(string[] args) { // 创建 SavingsAccount 的对象 SavingsAccount objSavingsAccount = new SavingsAccount(12345, 5000);; Console.WriteLine("输入到现在为止已获得的利息和利率"); objSavingsAccount.InterestEarned = Int64.Parse(Console.ReadLine()); SavingsAccount.InterestRate = Int64.Parse(Console.ReadLine()); objSavingsAccount.InterestEarned += objSavingsAccount.Balance * SavingsAccount.InterestRate; Console.WriteLine("获得的总利息为: {0}", objSavingsAccount.InterestEarned); } public static double InterestRate { get { return _interestRate; } set { // 验证数据 if (value < 0.0) { Console.WriteLine(“利率不能为负数"); return; } else { _interestRate = value / 100; } } 将设置 InterestRate属性
定义和调用属性 static void Main(string[] args) { // 创建 SavingsAccount 的对象 SavingsAccount objSavingsAccount = new SavingsAccount(12345, 5000);; Console.WriteLine(“输入到现在为止已获得的利息和利率"); objSavingsAccount.InterestEarned = Int64.Parse(Console.ReadLine()); SavingsAccount.InterestRate = Int64.Parse(Console.ReadLine()); objSavingsAccount.InterestEarned += objSavingsAccount.Balance * SavingsAccount.InterestRate; Console.WriteLine("获得的总利息为: {0}", objSavingsAccount.InterestEarned); } public double Balance { get { if (_balance < 0) Console.WriteLine("没有可用余额"); return _balance; } } 将检索 Balance和 InterestRate属性
索引器 语法 [访问修饰符] 数据类型 this[数据类型 标识符] { get{}; set{}; }
定义和调用索引器 以 Title属性表示照片 将照片存放于数组 photos 中 class Photo { string _title; public Photo(string title) { this._title = title; } public string Title { get { return _title; } } } class Album { // 该数组用于存放照片 Photo[] photos; public Album(int capacity) { photos = new Photo[capacity]; } 演示……
public Photo this[int index] { get { // 验证索引范围 if (index < 0 || index >= photos.Length) { Console.WriteLine("索引无效"); // 使用 null 指示失败 return null; } // 对于有效索引,返回请求的照片 return photos[index]; } set { if (index < 0 || index >= photos.Length) { Console.WriteLine("索引无效"); return; } photos[index] = value; } } 定义和调用索引器 带有 int参数的 Photo索引器 读/写索引器
定义和调用索引器 带有 string参数的 Photo索引器 public Photo this[string title] { get { // 遍历数组中的所有照片 foreach (Photo p in photos) { // 将照片中的标题与索引器参数进行比较 if (p.Title == title) return p; } Console.WriteLine("未找到"); // 使用 null 指示失败 return null; } } 只读索引器
定义和调用索引器 static void Main(string[] args) { // 创建一个容量为 3 的相册 Album friends = new Album(3); // 创建 3 张照片 Photo first = new Photo("Jenn"); Photo second = new Photo("Smith"); Photo third = new Photo("Mark"); // 向相册加载照片 friends[0] = first; friends[1] = second; friends[2] = third; // 按索引检索 Photo obj1Photo = friends[2]; Console.WriteLine(obj1Photo.Title); // 按名称检索 Photo obj2Photo = friends["Jenn"]; Console.WriteLine(obj2Photo.Title); }
委托 在运行时确定调用哪种方法 Multiply(int,int) { …. } Divide(int,int) { …. } --- public delegate Call(int num1, int num2); --- 委托和方法必须具有相同的签名
定义委托 class Delegates { public delegate int Call(int num1, int num2); class Math { public int Multiply(int num1, int num2) { // 实现 } public int Divide(int num1, int num2) {// 实现 } } class TestDelegates { static void Main() { Call objCall; Math objMath = new Math(); objCall = new Call(math.Multiply); } } 语法 [访问修饰符] delegate 返回类型 委托名(); 将方法与委托关联起来
定义委托 class Delegates { // 委托定义 public delegate int Call(int num1, int num2); class Math { // 乘法方法 public int Multiply(int num1, int num2) { return num1*num2; } // 除法方法 public int Divide(int num1, int num2) { return num1/num2; } } 将方法与委托关联起来 static void Main(string[] args) { // 委托的对象 Call objCall; // Math 类的对象 Math objMath = new Math(); // 将方法与委托关联起来 objCall = new Call(objMath.Multiply); // 将委托实例化 result = objCall(5, 3); System.Console.WriteLine("结果为 {0}", result); }
事件 宣布人 抢答者 抢答者 事件源 “请听题~” • 定义事件 • 为对象订阅该事件 • 将发生的事件通知给订阅人 事件的发布者 不关心 集中注意力聆听 未订阅该事件 其他人 事件的订阅人
定义事件 语法 [访问修饰符] event 委托名 事件名; public delegate void delegateMe(); private event delegateMe eventMe;
订阅事件 eventMe += new delegateMe(objA.Method); eventMe += new delegateMe(objB.Method);
通知订阅对象 if(condition) { eventMe(); } 调用订阅特定事件的对象的所有委托
示例 class Delegate { // 定义委托 public delegate void MeDelegate(); // 定义事件 public event MeDelegate NotifyEveryOne; public void Notify() { // 如果事件不为 null if(NotifyEveryOne != null) { Console.WriteLine("触发事件:"); // 触发事件 NotifyEveryOne(); } } } class ClassA { public void DispMethod() { Console.WriteLine(“Class A 已接到 NotifyEveryOne 事件的通知!"); } } // 第二个类 class ClassB { public void DispMethod() { Console.WriteLine(“Class B 已接到 NotifyEveryOne 事件的通知! "); } } class TestEvents { [STAThread] static void Main(string[] args) { // 委托的对象 Delegate objDelegate = new Delegate(); // ClassA 的对象 ClassA objClassA = new ClassA(); // ClassB 的对象 ClassB objClassB = new ClassB(); // 订阅该事件 objDelegate.NotifyEveryOne += new Delegate.MeDelegate(objClassA.DispMethod); objDelegate.NotifyEveryOne += new Delegate.MeDelegate(objClassB.DispMethod); objDelegate.Notify(); } } 0 演示:示例 4
总结 • 属性通过使用访问器读取和写入类中的字段,对字段进行保护 • 属性分类为以下四种不同的类型: • 读/写属性 • 只读属性 • 只写属性 • 可以在类中定义索引器,允许使用下标对该类的对象中的数据进行访问 • 索引器必须总是命名为 this,因为对它们的访问是通过其所属的对象进行的 • 委托包含对方法而不是方法名称的引用 • C# 中的事件允许一个对象将发生的事件或修改通知其他对象