泛型
-
广泛的类型: 泛型类, 泛型方法, 泛型集合, 泛型接口, 泛型委托.
-
泛型的运用主要在 泛型集合.
-
泛型类的约束: 关键字 where
- where T: struct
- 约束 T 为值类型, 因为在 c# 语言中所有的值类型都是用 struct 结构去定义的.
- where T: class
- 约束 T 为引用类型
- where T: new()
- 约束 T 为含有 public 无参构造函数的类型
- 基本的值类型有, 引用类型没有
- 自定义的类是可以的
- where T:K
- 约束 T 为 K 的子类
- where T:IMyInterface
- 约束 T 必须为 IMyInterface 的实现类
- where T: struct
-
值类型和引用类型的复习
- 值类型: 整型 + 浮点型 + 字符 + 布尔 + 日期 + 枚举 + 结构
- 应用类型: 字符串 + 数组 + 类 + 接口 + 委托
/*
* 1.泛型方法
* 2.泛型类
* 3.泛型类中的泛型方法
* 4.两个参数的泛型类
* 5.泛型的约束
*/
using System;
namespace GenericTest
{
class class1
{
// 1. 泛型方法的定义
public void Show<T>(T t)
{
Console.WriteLine("This is {0} and parameter is {1}",typeof(class1).Name, t.GetType().Name);
}
}
//2,4. 泛型类
class GenericClass<T>
{
//声明两个泛型的变量
T a;
T b;
//构造函数
public GenericClass(T a,T b)
{
this.a = a;
this.b = b;
}
//方法输出两个字段的拼接
public string Combine()
{
return this.a.ToString() + this.b.ToString();
}
//3. 泛型类中的泛型方法, 注意不用写尖括号
public void Sum(T a, T b) { }
}
//5. 两个参数的泛型类, 并对泛型进行约束
class GenericClass2<T, K, A, B>
where T : struct //T 必须为值类型
where K : class //K 必须为引用类型
where A : new() //A 必须定义无参 public构造函数
where B : K //K 必须是 B 的父类
{
T a;
K b;
// 泛型类的构造函数
public GenericClass2(T a, K b)
{
this.a = a;
this.b = b;
}
}
// 主程序
class Program
{
static void Main(string[] args)
{
#region 泛型方法
class1 c1 = new class1();
// 泛型方法的调用方法.
c1.Show<int>(100);
// 此方法也能够输出参数的类型, 证明泛型也能够这样调用.
c1.Show("ss");
#endregion
#region 泛型类
// 调用构造函数需要指定参数类型.
GenericClass<int> g1 = new GenericClass<int>(123, 456);
GenericClass<string> g2 = new GenericClass<string>("aa", "ple");
string res1 = g1.Combine();
string res2 = g2.Combine();
Console.WriteLine(res1); // 输出 123456
Console.WriteLine(res2); // 输出 123456
#endregion
}
}
}
集合
集合和数组的比较
- 数组: 长度固定, 有序, 元素类型相同
- 集合: 长度可变, 有序, 元素类型可以不同. 泛型集合可以规定元素类型.
常用集合的分类
- 传统集合
- 有序集合: ArrayList 动态数组, 元素类型可以不相同
- 键值对集合: HashTable 哈希表, 元素类型可以不相同
- 泛型集合
- 有序集合: List
, 元素类型必须相同 - 键值对集合: Dictionary<K,V>, 元素类型必须相同
- 有序集合: List
ArrayList 的操作
- 创建: ArrayList al = new ArrayList(length)
- 添加元素: add( object v)
- 装箱的过程: 值类型存到引用类型的过程
- 拆箱的过程: 把集合内的元素提取出来赋值(比如 int), 有时候需要拆箱: 把引用转值.
- object 是所有变量类型的顶层父级, 传参可以穿参数的子类, 所以 add 方法可以传任何形式的变量.
- 当添加的元素数量超过动态数组长度的时候, 长度会自动翻倍.
- 剩下的懒得写了, 直接写在代码实例里了.
/*
* 1.创建
* 2.添加
* 3.获取
* 4.插入
* 5.插入一组
* 6.删除
* 7.排序
* 8.颠倒
*/
using System;
using System.Collections;
namespace CollectionTest
{
class Program
{
static void Main(string[] args)
{
//1. 创建长度为 10 的动态数组
ArrayList arrayList = new ArrayList(10);
//2. 添加一个整型到动态数组, 装箱
arrayList.Add(100);
//3. 获取元素, 拆箱
int a = Convert.ToInt32(arrayList[0]);
//4. 在 0 位置上插入一个整型, 后面的元素一次往后移位
//不能在最后一个元素之后的之后插入, 中间不能有空位
arrayList.Insert(0, 100);
//5. 插入一组数据, 两个参数一个是插入节点, 一个是实现了 ICollection 接口的数据类型
int[] list = { 1, 2, 3, 4 }; //初始化一个数组
arrayList.InsertRange(3, list);
//6. 删除元素
arrayList.Remove(100); //删除 100
arrayList.RemoveAt(0); //删除 第一个元素
arrayList.RemoveRange(0, 2); //删除 从 0 开始往后 2 个元素
//7. 元素排序和颠倒
arrayList.Sort(); //从小到大
arrayList.Reverse();
//8. 转换成数组, 长度为元素个数
Object[] arr = arrayList.ToArray();
//循环遍历所有元素, count 为元素个数
for(int i = 0; i < arrayList.Count; i++)
{
Console.WriteLine(arrayList[i]);
}
}
}
}