精通C#--高级C#编程结构

#集合与泛型
集合类:
–非泛型集合【System.Collections,System.Collections.Specialized】
–泛型集合【System.Collections.Generic】

##非泛型集合
ArrayList
BitArray
Hashtable
Queue
SortedList
Stack

HybridDictionary
ListDictionary
StringCollection
BitVector32

相关接口:
ICollection 为所有非泛型集合类型定义基本特性
ICloneable 为实现它的对象,向调用者返回对象的副本
IDictionary 允许非泛型集合对象使用名称/值对来表示其内容
IEnumerable
IEnumerator
IList

2.非泛型集合一般针对的对象类型是System.Object

装箱:把值类型数据保存在引用类型变量中。

static void SimpleBoxUnboxOperation()
{
	int myInt = 25;
	// 显式地将值类型分配给System.Object变量的过程
	// 对值类型进行装箱时,CLR会在堆上分配新的对象并且将值类型的值复制到那个实例上。因此,返回给我们的就是新分配在堆上的对象的引用。
	object boxedInt = myInt;
}

拆箱:把保存在对象引用中的值转换回栈上的相应值类型。

static void SimpleBoxUnboxOperation()
{
	int myInt = 25;
	object boxedInt = myInt;
	// CLR会验证收到的值类型是不是等价于装箱的类型。
	// 如果是,就将值复制回本地栈变量上。
	// 如果不是,将抛出InvalidCastException异常。
	int unboxedInt = (int)boxedInt;
}

在传递给需要object的方法时,值类型会自动装箱。

static void WorkWithArrayList()
{
	ArrayList myInts = new ArrayList();
	// 在传递给需要object的方法时,值类型会自动装箱
	myInts.Add(10);
	myInts.Add(20);
	myInts.Add(35);
	
	// 当将object转换回栈数据时,会发送拆箱
	int i = (int)myInts[0];
	Console.WriteLine("Value of your int:{0}", i);
}

装箱和拆箱时细节:
在托管堆上分配一个新对象
基于栈数据的值必须被转移到新分配的内存位置
在拆箱时,保存在堆对象中的值必须转移回栈
堆上无用的对象【最后】会被回收

##泛型集合
1.
与非泛型容器相比,泛型容器的一些优势
提供了更好的性能,因为没有装箱和拆箱过程
更类型安全,因为只包含我们指定的类型
大幅减少了构建自定义集合类型的需要

2.只有类,结构,接口,委托可以使用泛型,枚举类型不可以。
泛型的类型参数的名称可以随意取。但通常,T表示类型,TKey或K表示键,TValue或V表示值。

3.非泛型接口指定类型参数

// 非泛型版本
public interface IComparable
{
	int CompareTo(object obj);
}

// 泛型版本
public interface IComparable<T>
{
	int CompareTo(T obj);
}

public class Car : IComparable<Car>
{
	...
	// IComparable<T>的实现
	int IComparable<Car>.CompareTo(Car obj)
	{
		if(this.CarID > obj.CarID)
			return 1;
		if(this.CarID < obj.CarID)
			return -1;
		else
			return 0;
	}
}

4.System.Collections.Generic

// 泛型接口
ICollection<T>
ICompare<T>
IDictionary<TKey, TValue>
IEnumerable<T>
IEnumerator<T>
IList<T>
ISet<T>

// 泛型类
Dictionary<TKey, TValue>
LinkedList<T>
List<T>
Queue<T>
SortedDictionary<TKey, TValue>
SortedSet<T>
Stack<T>
HashSet<T>

对象初始化语法。
集合初始化语法:
只能对支持Add()方法的类使用集合初始化语法。

// 初始化标准数组
int[] myArrayOfInts = {0, 1, 2, 3};
// 初始化int的泛型List<>
List<int> myGenericList = new List<int>{0, 1, 2, 3};
// 用数字数据初始化ArrayList
ArrayList myList = new ArrayList{0, 1, 2, 3};

// 综合使用对象初始化和集合初始化
List<Point> myListOfPoints = new List<Point>
{
	new Point{X=2, Y=2},
	new Point{X=3, Y=3},
	new Point(PointColor.BloodRed){X=4, Y=4}
};

6.System.Collections.ObjectModel

ObservableCollection<T>		添加,移除项或刷新整个列表时提供通知的动态数据集合
ReadOnlyObservableCollection<T>


// ObservableCollection<T>实现了与List<T>相同的核心接口。不同的是,ObservableCollection<T>实现了一个名为CollectionChanged的事件。该事件将在插入新项,移除当前项或修改整个集合时触发。
// CollectionChanged定义为委托【这里为NotifyCollectionChangedEventHandler】
// 该委托可以调用任何以object为第一个参数,以NotifyCollectionChangedEventArgs为第二个参数的方法
class Program
{
	static void Main()
	{
		ObservableCollection<Person> people = new ObservableCollection<Person>()
		{
			new Person{FirstName="Peter", LastName="Murphy", Age=52},
			new Person{FirstName="Kevin", LastName="Key", Age=48},
		};

		people.CollectionChanged += people_CollectionChanged;
	}

	static void people_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
	{
		Console.WriteLine("Action for this event:{0}", e.Action);
		if(e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
		{
			Console.WriteLine("Here are the OLD items:");
			foreach (Person p in e.OldItems)
			{
				Console.WriteLine(p.ToString());
			}
			
			Console.WriteLine();
		}

		if(e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
		{
			Console.WriteLine("Here are the NEW items:");
			foreach(Person p in e.NewItems)
			{
				Console.WriteLine(p.ToString());
			}
		}
	}
} 

7.自定义泛型方法

static void Swap<T>(ref T a, ref T b)
{
	Console.WriteLine("You sent the Swap() method a {0}", typeof(T));
	T temp;
	temp = a;
	a = b;
	b = temp;
}

static void Main()
{
	Console.WriteLine("******Fun with custom Generic Methods ******\n");
	int a = 10, b = 90;
	Console.WriteLine("Before swap:{0}, {1}", a, b);
	Swap<int>(ref a, ref b);
	Console.WriteLine("After swap:{0}, {1}", a, b);
	Console.WriteLine();

	string s1 = "Hello", s2 = "There";
	Console.WriteLine("Before swap:{0} {1}", s1, s2);
	Swap<string>(ref s1, ref s2);
	Console.WriteLine("After swap:{0} {1}", s1, s2);
	Console.ReadLine();
}

当使用泛型时,不指定类型参数时,编译器会基于成员参数推断类型参数。
类型参数推断只在泛型方法至少有一个参数时起作用。

8.自定义泛型结构和类

public struct Point<T>
{
	private T xPos;
	private T yPos;
	public Point(T xVal, T yVal)
	{
		xPos = xVal;
		yPos = yVal;
	}

	public T X
	{
		get{return xPos;}
		set{xPos = value;}
	}

	public T Y
	{
		get{return xPos;}
		set{xPos = value;}
	}

	public override string ToString()
	{
		return string.Format("[{0},{1}]", xPos, yPos);
	}

	public void ResetPoint()
	{
		// default(类型参数) 返回一个类型参数的默认值
		xPos = default(T);
		yPos = default(T);
	}
}

9.类型参数的约束
任何泛型项须至少有一个类型参数,并在与泛型类型或参数交互时指定该类型参数。
使用where可以对给定的类型参数添加一组约束。
where T : ???
???:
struct 类型参数T须在其继承链中包含System.ValueType值类型。
class 类型参数T不能在其继承链中包含System.ValueType值类型。
new() 类型参数T须包含一个默认的构造函数。【在有多个约束的类型上,此约束须列在末尾】
NameOfBaseClass 类型参数T须派生于NameOfBaseClass指定的类
NameOfInterface 类型参数T须实现NameOfInterface指定的接口

// 类型参数T为引用类型,且实现了IDrawable,且具备默认构造
// 要为多个类型参数指定多个约束集时,用多个where语句
// where也可以用在限制泛型方法中的类型参数
public class MyGenericClass<T> where T : class, IDrawable, new()
{
	...
}

目前版本不支持对泛型的类型参数应用C#操作符

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值