using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; //使用Hashtable时,必须引入这个命名空间 class hashtable { public static void Main() { Hashtable ht = new Hashtable(); //创建一个Hashtable实例 ht.Add("E", "e");//添加keyvalue键值对 ht.Add("A", "a"); ht.Add("C", "c"); ht.Add("B", "b"); string s = (string)ht["A"]; Console.WriteLine(s); ArrayList akeys=new ArrayList(ht.Keys); //别忘了导入System.Collections akeys.Sort(); //按字母顺序进行排序 foreach(string skey in akeys) { Console.Write(skey + ":"); Console.WriteLine(ht[skey]);//排序后输出#### } if (ht.Contains("E")) //判断哈希表是否包含特定键,其返回值为true或false Console.WriteLine("the E key exist"); ht.Remove("C");//移除一个keyvalue键值对 foreach(DictionaryEntry de in ht) //ht为一个Hashtable实例 { Console.Write(de.Key + " ");//de.Key对应于keyvalue键值对key Console.WriteLine(de.Value);//de.Key对应于keyvalue键值对value } Console.WriteLine(ht["A"]);//此处输出a### ht.Clear();//移除所有元素 Console.WriteLine(ht["A"]); //此处将不会有任何输出 } }
Hashtable的遍历:与数组类似,都可以使用foreach语句。这里学要注意的是:由于Hashtable重的元素是一个键/值对,因此需要使用DictionaryEntry类型来进行遍历。
DictionaryEntry类型表示一个键/值对的集合。
using System; using System.Collections.Generic; using System.Linq; using System.Text; interface IEmployee { string Name { get; set; } int Counter { get; } } public class Employee { public static int numberOfEmployees; private string name; public string Name { get { return name; } set { name = value; } } private int counter; public int Counter { get { return counter; } } public Employee() { counter = ++counter + numberOfEmployees; } } class Program { static void Main() { System.Console.Write("Enter number of employees: "); Employee.numberOfEmployees = int.Parse(System.Console.ReadLine()); Employee e1 = new Employee(); System.Console.Write("Enter the name of the new employee: "); e1.Name = System.Console.ReadLine(); System.Console.WriteLine("The employee information:"); System.Console.WriteLine("Employee number: {0}", e1.Counter); System.Console.WriteLine("Employee name: {0}", e1.Name); } }
接口属性:接口属性的访问器不具有体。因此,访问器的用途是指示属性是否为读写、只读或只写。
可以使用属性的完全限定名,它引用声明成员的接口。例如:
string IEmployee.Name { get { return "Employee Name"; } set { } }
这被称为显式接口实现(C# 编程指南)。例如,如果 Employee 类实现两个接口 ICitizen 和 IEmployee,并且两个接口都具有 Name 属性,则需要显式接口成员实现。即,如下属性声明:
string IEmployee.Name { get { return "Employee Name"; } set { } }
接口:由于C#中的类不支持多重继承,但是客观世界出现多重继承的情况比较多。因此为了避免传统的多继承该程序带来的复杂性等问题,同时保证多继承带给程序员的诸多好处,
提出了接口的概念。接口可由方法,属性,事件和索引器等组成。但不包含字段。
在重写属性或索引器时,被重写的访问器对重写代码而言,必须是可访问的。此外,属性/索引器和访问器的可访问性级别都必须与相应的被重写属性/索引器和访问器匹配。例如:
public class Parent { public virtual int TestProperty { // Notice the accessor accessibility level. protected set { } // No access modifier is used here. get { return 0; } } } public class Kid : Parent { public override int TestProperty { // Use the same accessibility level as in the overridden accessor. protected set { } // Cannot use access modifier here. get { return 0; } } }
public class BaseClass { private string name = "Name-BaseClass"; private string id = "ID-BaseClass"; public string Name { get { return name; } set { } } public string Id { get { return id; } set { } } } public class DerivedClass : BaseClass { private string name = "Name-DerivedClass"; private string id = "ID-DerivedClass"; new public string Name { get { return name; } // Using "protected" would make the set accessor not accessible. set { name = value; } } // Using private on the following property hides it in the Main Class. // Any assignment to the property will use Id in BaseClass. new private string Id { get { return id; } set { id = value; } } } class MainClass { static void Main() { BaseClass b1 = new BaseClass(); DerivedClass d1 = new DerivedClass(); b1.Name = "Mary"; d1.Name = "John"; b1.Id = "Mary123"; d1.Id = "John123"; // The BaseClass.Id property is called. System.Console.WriteLine("Base: {0}, {1}", b1.Name, b1.Id); System.Console.WriteLine("Derived: {0}, {1}", d1.Name, d1.Id); } }
索引器
using System; using System.Collections.Generic; using System.Linq; using System.Text; class IndexerClass { private int[] arr = new int[100]; public int this[int index] { get { if (index < 0 || index >= 100) { return 0; } else { return arr[index]; } } set { if (!(index < 0 || index >= 100)) { arr[index] = value; } } } } class MainClass { static void Main() { IndexerClass test = new IndexerClass(); test[3] = 256; test[5] = 1024; for (int i = 0; i < 100; ++i) { Console.WriteLine("Element #{0} = {1}",i,test[i]); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; class DayCollection { string[] days = { "Sun","Mon","Tues","Wed","Thus","Fri","Sat"}; //This mathod finds the day or returns -1 private int GetDays(string testDay) { int i = 0; foreach(string day in days) { if(day == testDay) { return i; } ++ i; } return -1; } //The get accessor returns an interger for a given string public int this[string day] { get { return (GetDays(day)); } } } class Program { static void Main() { DayCollection week = new DayCollection(); Console.WriteLine(week["Fri"]); Console.WriteLine(week["Made-up Day"]); } }
C# 并不将索引类型限制为整数。例如,对索引器使用字符串可能是有用的。通过搜索集合内的字符串并返回相应的值,可以实现此类的索引器。由于访问器可被重载,字符串和整数版本可以共存。
using System; using System.Collections.Generic; using System.Linq; using System.Text; public interface ISomeInterface { int this[int index] { get; set; } } class IndexerClass : ISomeInterface { private int[] arr = new int[100]; public int this[int index] { get { if (index < 0 || index >= 100) { return 0; } else { return arr[index]; } } set { if (!(index < 0 || index >= 100)) { arr[index] = value; } } } } class MainClass { static void Main() { IndexerClass test = new IndexerClass(); test[2] = 4; test[5] = 32; for (int i = 0; i <= 10; ++i) { Console.WriteLine("Element #{0} = {1}",i,test[i]); } } }
在上例中,可以通过使用接口成员的完全限定名来使用显式接口成员实现。例如:
public string ISomeInterface.this { }
但是,只有当类使用同一索引器签名实现一个以上的接口时,为避免多义性才需要使用完全限定名。例如,如果 Employee 类实现的是两个接口 ICitizen 和 IEmployee,并且这两个接口具有相同的索引器签名,则必须使用显式接口成员实现。即,以下索引器声明:
public string IEmployee.this { }
在 IEmployee 接口上实现索引器,而以下声明:
public string ICitizen.this { }
在 ICitizen 接口上实现索引器。