目录
第十一章 集合、比较和转换
第十一章 集合、比较和转换
- 集合:可以使用集合来维护数组,控制对它们对象的访问、搜索和排序等。
- 比较:在处理对象时常用到它们。这对于集合尤其重要,因为这是排序的实现方式。
- 转换:定制类型转换,以满足自己的需要。
11.1集合
数组一旦建好,其大小是固定的。
集合类一般用于处理对象列表,其功能比简单数组要多,功能大多是通过实现System.Collections名称空间中的接口而获得的,因此集合的语法已经标准化了。
集合的功能(包括基本功能,例如,用【index】语法访问集合中的项)可以通过接口来实现。
System.Collections名称空间中的几个接口提供了基本的集合功能:
- IEnumerable——可以迭代集合中的项(单词解释:enumerable-adj. 可列举的;可点数的)
- ICollection——(继承于IEnumerable)可以获取集合中项的个数,并能把项复制到一个简单的数组类型。
- IList——(继承于IEnumerable和ICollection)提供了集合的项列表,允许访问这些项,并提供其他一些与列表相关的基本功能。
- IDictionary——(继承于IEnumerable 和IColleciton)类似于IList,但提供了可通过键值(而不是索引)访问的项列表。
11.1.1 使用集合
1-->创建三个类,Animal,Cow,Chicken,Cow:Animal,Chicken:Animal;
Animal.cs
namespace Ch11Ex01
{
//Define a abstract class Animal
public abstract class Animal
{
//protected ,to access the domain in the class(Animal) or in a class extends the class(Animal)
protected string name;
public string Name //attention please,the capital of Name
{
get
{
return name;
}
set
{
name = value;
}
}
//To define a method
public Animal()
{
name = "The animal with no name";
}
//To define a method with parameter
public Animal(string newName)
{
name = newName;
}
//To define a method without returned value
public void Feed()
{
Console.WriteLine("{0} has been fed.",name);
}
}
}
Cow.cs
namespace Ch11Ex01
{
//Define a class(Cow)to extend Animal
class Cow : Animal
{
//Define a method to describe animals' actions
public void Milk()
{
Console.WriteLine("{0} has been milked.",name);
}
//base关键字指定.NET实例化过程使用基类中具有指定参数的构造函数。
public Cow(string newName)
: base(newName)
{
}
}
}
Chicken.cs
namespace Ch11Ex01
{
public class Chicken : Animal
{
//Chicken类中定义了两个方法,一个是自定义,一个是利用base引用基类函数
public void LayEgg()
{
Console.WriteLine("{0} has laid an egg.",name);
}
public Chicken(string newName)
: base(newName)
{
}
}
}
2--->创建主类,Program.cs,类的主函数创建忘了两个对象集合,第一个集合使用System.Array(简单数组),第二个集合是System.Collection.ArrayList类。剩余部分利用了一些ArrayList集合功能超出了Array集合的功能范围。
第一个创建数组
//第一行:创建一个数组类型,并使用
//第二行:对Animal进行实例化此处的数组大小要根据内容设定,不然会报错
//第三行:对Cow实例化,使用带参函数,体现出了面向对象开发的多态性
//第四行:
/*分别对数组对象复制,第一个将myCow1(一个对象,经过Cow实例化后得到的返回值)
*派生类(Cow)
* public Cow(string newName): base(newName){}
*基类
* public Animal(string newName)
* {
* name = newName;
* }
* 赋值给数组第一个变量
* 结果:Deirdre
*/
//第五行:
/*
*此处直接获得Chicken里的带一个参数的返回值对象
* public Chicken(string newName): base(newName){}
* 结果:Ken
*/
Console.WriteLine("Create an Array type collection of Animal object and use it:");
Animal[] animalArray = new Animal[2];
Cow myCow1 = new Cow("Deirdre");
animalArray[0] = myCow1;
animalArray[1] = new Chicken("Ken");
//第一行:使用迭代循环,并定义了myAnimal类型为Animal类型
//第二行:输出myAnimal的类型和所带属性
//第三行:输出animalArray数组长度
//第四行:调用Animal自带的Feed()函数
//第五行:调用Chicken里的LayEgg()方法,由于animalArray本来是Animal类型,所以调用Chicken的方法,要进行强制类型转换
foreach (Animal myAnimal in animalArray)
{
Console.WriteLine("New {0} object added to Array collection Name = {1}", myAnimal.ToString(), myAnimal.Name);
}
Console.WriteLine("Array collection contains {0} objects.", animalArray.Length);
animalArray[0].Feed();
((Chicken)animalArray[1]).LayEgg();
Console.WriteLine();
运行结果:
3--->整体
namespace Ch11Ex01
{
class Program
{
static void Main(string[] args)
{
//第一行:创建一个数组类型,并使用
//第二行:对Animal进行实例化此处的数组大小要根据内容设定,不然会报错
//第三行:对Cow实例化,使用带参函数,体现出了面向对象开发的多态性
//第四行:
/*分别对数组对象复制,第一个将myCow1(一个对象,经过Cow实例化后得到的返回值)
*派生类(Cow)
* public Cow(string newName): base(newName){}
*基类
* public Animal(string newName)
* {
* name = newName;
* }
* 赋值给数组第一个变量
* 结果:Deirdre
*/
//第五行:
/*
*此处直接获得Chicken里的带一个参数的返回值对象
* public Chicken(string newName): base(newName){}
* 结果:Ken
*/
Console.WriteLine("Create an Array type collection of Animal object and use it:");
Animal[] animalArray = new Animal[2];
Cow myCow1 = new Cow("Deirdre");
animalArray[0] = myCow1;
animalArray[1] = new Chicken("Ken");
//第一行:使用迭代循环,并定义了myAnimal类型为Animal类型
//第二行:输出myAnimal的类型和所带属性
//第三行:输出animalArray数组长度
//第四行:调用Animal自带的Feed()函数
//第五行:调用Chicken里的LayEgg()方法,由于animalArray本来是Animal类型,所以调用Chicken的方法,要进行强制类型转换
foreach (Animal myAnimal in animalArray)
{
Console.WriteLine("New {0} object added to Array collection Name = {1}", myAnimal.ToString(), myAnimal.Name);
}
Console.WriteLine("Array collection contains {0} objects.", animalArray.Length);
animalArray[0].Feed();
((Chicken)animalArray[1]).LayEgg();
Console.WriteLine();
//第二个集合是System.Collection.ArrayList类
Console.WriteLine("Create an ArrayList type collection of Animal objects and use it:");
ArrayList animalArrayList = new ArrayList();
Cow myCow2 = new Cow("Hayley");
animalArrayList.Add(myCow2);
animalArrayList.Add(new Chicken("Roy"));
foreach (Animal myAnimal in animalArrayList)
{
Console.WriteLine("New {0} object added to ArrayList collection Name = {1}", myAnimal.ToString(), myAnimal.Name);
}
Console.WriteLine("ArrayList colleciton contains {0} objects.", animalArrayList.Count);
((Animal)animalArrayList[0]).Feed();
((Chicken)animalArrayList[1]).LayEgg();
Console.WriteLine();
//利用了一些ArrayList集合功能超出了Array集合的功能范围
Console.WriteLine("Additional manipulation of ArrayList:");
animalArrayList.RemoveAt(0);
((Animal)animalArrayList[0]).Feed();
animalArrayList.AddRange(animalArray);
((Chicken)animalArrayList[2]).LayEgg();
Console.WriteLine("The animal called{0} is at index {1}.", myCow1.Name, animalArrayList.IndexOf(myCow1));
myCow1.Name = "Janice";
Console.WriteLine("The animal is now called {0}.", ((Cow)animalArrayList[1]).Name);
Console.ReadKey();
}
}
}
运行结果:
11.1.2 定义集合
如何创建自己的强类型化的集合?一种方式是手动实现需要的方法但比较费时间,在某些情况下也非常复杂。我们可以从一个类中派生自己的集合,例如System.Collections.CollectionBase类,这个抽象类提供了集合类的大量实现代码。
11.1.3 索引符
索引符(indexer)是一种特殊类型的属性,可以把它添加到一个类中,以提供似于数组的访问。
11.2 比较
1.封箱与拆箱
封箱(boxing)是把值类型转换为System.Object类型,或者转换为由值类型实现的接口类型。拆箱(unboxing)是相反的转换过程。
在.net中的通用类型系统(Common Type system,CTS)中,所有类型都是对象(object),都派生自System.Object。
CTS支持两组类型:值类型和引用类型。如果变量是值类型那么这个变量就包含实际的数据。也就是在内存中确实会分配那么一部分空间给这个变量并存储值,引用类型就类似一个类型安全的指针,本身并没有开辟内存空间去存储东西(拆箱装箱之前要先了解這些).
装箱是将值类型转换为引用类型。
拆箱就是将引用类型转换为值类型。
装箱就是把值类型转换成引用类型,反之就是拆箱
int a=5;
string ss=a;装箱
int a2=int.Parse(ss);拆箱
2 . is运算符
此图片可省略,哈哈 is运算符并不是用来说明对象是某种类型,而是用来检查对象是不是给定类型,或者是否可以转换为给定类型,如果是,这个运算符就返回true。
is 与 as 的比较
is运算符
is运算符可以检查对象是否与特定的类型兼容。is运算符用来检查对象(变量)是否属于某数据类型(如int、string、bool、double、class等),可在安全类型转换之前进行判断之用。
例如,要检查变量是否与object类型兼容: 注意:“兼容”表示对象是该类型,或者派生于该类型。
int i = 10;
if (i is object)
{
Console.WriteLine("i is an object");
}
int和从object继承而来的其他C#数据类型一样,表达式i is object将得到true,并显示信息。
as运算符
as运算符用于执行引用类型的显式类型转换。如果要转换的类型与指定的类型兼容,转换就会成功进行;如果类型不兼容,as运算符就会返回值null。如下面的代码所示,如果object引用不指向string实例,把object引用转换为string就会返回null:
object o1 = "Some String";
object o2 = 5;
string s1 = o1 as string; //s1 = "Some String"
string s2 = o2 as string; //s2 = null
as运算符允许在一步中进行安全的类型转换,不需要先使用is运算符测试类型,再执行 转换
11.3 转换
这一节讲的就是采用不同的方式进行类型转换,显式,隐式,as的不同方式的使用。
网友评论