C#编程语言进阶
1.ArrayList
ArrayList概念:
ArrayList 是 C# 中的一个动态数组,它可以根据需要自动调整大小,并允许在列表中进行动态内存分配、增加、搜索和排序各项。ArrayList是一个C#为我们封装好的类,它的本质是一个object类型的数组。(也就是说一个ArrayList中可以存储不同类型的数据)
ArrayList的声明
ArrayList的声明需要引用命名空间using System.Collections;命名空间
ArrayList array = new ArrayList();
ArrayList的使用
1.增加的操作
ArrayList array = new ArrayList();
// 单个元素增加,在数组尾部添加
array.Add(1);
array.Add("123");
array.Add("Unity");
foreach(var t in array)
{
Console.WriteLine(t); // 输出:1,123,Unity
}
ArrayList array2 = new ArrayList();
array2.Add("Game");
// 增加范围(批量增加,把另外一个ArrayList里的内容添加到后面)
// AddRange方法通常用于将一个集合(如数组、列表等)中的所有元素添加到另一个集合中,
// 不直接接受多个单独的参数。
array2.AddRange(array2);
array.AddRange(new string[] {"Orange", "Grape"}); // 添加多个元素
// 在指定位置增加(插入)
array.Insert(1, "Banana"); // 在指定位置插入
2.删操作
// 移除指定元素(如果数组中有两个相同的元素删除前面那个)
array.Remove(1);
// 移除指定位置的元素
array.RemoveAt(3);
// 移除移除一定范围的元素
array.RemoveRange(1,4); // 不是左开右闭区间,而是从指定位置开始移除指定数量的元素
// 清空
array.Clear();
3.查操作
// 通过索引访问
object fruit = array[3];
// 查看元素是否存在
array.Contains("123") // 返回值为bool值
// 查看元素数量
int count = array.Count;
// 获取索引
// 正向查找
// 找到则返回元素位置,没有则返回-1
// 若有相同元素查找的是第一个元素
int index = array.IndexOf("Unity");
// 逆向查找
// 返回的从头开始的索引数
int index = array.LastIndexOf("123");
遍历
1.获取长度
// 获取元素个数
array.Count;
// 获取容量
// 避免产生更多的垃圾
array.Capacity;
2.遍历
1.for循环遍历
for(int i; i<array.Count;i++)
{
}
2.foreach 迭代器遍历
foreach(var item in array)
{
}
2.Stack(栈)
概念:
Stack是C#为我们封装好的类,它的本质也是一个object类型的数组,只是封装了特殊的存储规则。Stack(栈),先进后出的规则
Stack声明:
Stack stack = new Stack();
Stack使用:
1.增加(压栈)操作
// 增
stack.Push(1);
stack.Push("Stack");
stack.Push(true);
2.取(弹栈)操作
object v = stack.Pop();
3.查的操作(只能查看栈顶元素)
栈无法查看指定元素,只能查看栈顶元素(即最后入栈的元素)
object v = stack.Peek();
// 查看是否存在于栈中
stack.Contains(1);
4.改的操作
栈无法改变其中元素,只能压栈和弹栈。实在要改,只有清空
stack.Clear();
5.遍历
栈不能用for循环遍历,只能用foreach遍历
// foreach迭代器遍历
foreach(var item in stack)
{
}
// 将栈转变成object数组
// 遍历出来的顺序也是从栈顶到栈底
object[] array = stack.ToArray();
for(int i = 0; i < array.Length; i++)
{
}
3.Queue(队列)
队列概念:
Queue 是一种先进先出(FIFO - First In First Out)的线性数据结构。
队列的声明:
Queue queue = new Queue();
队列的使用:
1.增加操作
queue.Enqueue(1);
queue.Enqueue("Unity");
2.取操作
先进先出
object v = queue.Dnqueue();
3.查操作
查看队首元素(即最早入队的元素)
queue.Peek();
// 查看元素是否存在
queue.Contains("Unity");
4.改操作
队列无法改变其中的元素,只能进出队列。实在要改,只有清空
queue.Clear();
4.Hashtable(散列表、哈希表)
Hashtable概念
Hashtable是一个非泛型的键值对集合,它通过哈希表实现,允许通过键快速查找值。是基于键的哈希代码组织起来的 键/值 对。(注意:Hashtable都是通过键去映射值,不能通过值反过来去查找键的,因为值可以重复,键是唯一的)
Hashtable声明
Hashtable hashtable = new Hashtable();
Hashtable的使用:
增加操作:
hashtable.Add(键key,值value);
// 注意:键和值可以是任意类型(但不能出现相同的键)
hashtable.Add(1,"111");
hashtable.Add(2,"222");
删除操作:
// 哈希表名.Remove(键); 只能通过键值去删
// 删除不存在的键,没反应
hashtable.Remove(1);
// 清空
hashtable.Clear();
查找操作:
// 哈希表名[键]; 返回键对应的值,不存在返回null
hashtable[1];
// 查看是否存在
// 哈希表名.ContainsKey(); 返回bool值,存在返回true,不存在返回false
// 通过键去找
// 法一:
hashtable.Contains(键Key);
// 法二:
hashtable.ContainsKey(键Key);
// 通过值去找
hashtable.ContainsValue(值value);
改操作:
// 只能改键对应的值,不能改键
// 哈希表名[键] = 值;
hashtable[Key] = Value;
遍历操作:
Console.WriteLine(hashtable.Count); // 得到键值对的数量
// 1. 遍历所有键
foreach (object key in hashtable.Keys)
{
Console.WriteLine(key);
}
// 2. 遍历所有值
foreach (object value in hashtable.Values)
{
Console.WriteLine(value);
}
// 3.键值对一起遍历
foreach (DictionaryEntry item in table)
{
Console.WriteLine(item.Key + " : " + item.Value);
}
// 4.迭代器遍历
IDictionaryEnumerator enumerator = table.GetEnumerator();
bool hasNext = enumerator.MoveNext();
while (hasNext)
{
Console.WriteLine(enumerator.Key + " : " + enumerator.Value);
}
5.泛型
泛型概念:
泛型实现了类型参数化,达到代码重用目的。通过类型参数化来实现同一份代码上操作多种类型。(使用泛型可以一定程度避免装箱拆箱)
泛型相当于类型占位符。定义类或者方法时使用替代符代表变量类型,当真正使用类或者方法时再具体指定类型。
泛型的声明:
1.泛型类
class 类名<泛型占位字母>
2.泛型接口
interface 接口名<泛型占位字母>
3.泛型函数
函数名<泛型占位字母>
注意:占位字母可以有多个,通过逗号隔开
泛型类:
class TestClass<T>
{
// 成员变量
public T value;
}
// 多个泛型
class TestClass2<T1, T2>
{
public T1 value1;
public T2 value2;
}
static void Main(string[] args)
{
TestClass<int> t = new TestClass<T>();
TestClass2<int, string> t = new TestClss2<int ,string>();
}
泛型接口:
interface TestInterface<T>
{
T Value
{
get;
set;
}
}
class Test<T> : TestInterface<T> // 类的 T 和接口的 T 是同一个类型
{
public T Value { get; set; }
}
static void Main(string[] args)
{
// 实例化 Test 类
Test test = new Test();
test.Value = 123; // 设置 Value
Console.WriteLine(test.Value); // 输出: 123
// 通过接口引用访问
// 将一个 Test类的实例 test赋值给一个 TestInterface<int>类型的变量 testInterface
TestInterface<int> testInterface = test;
Console.WriteLine(testInterface.Value); // 输出: 123
// Test类实现了 TestInterface<int>,所以 Test中的 public int Value { get; set; }就是接口 TestInterface<int>要求的 Value属性的具体实现。
}
泛型方法:
1.普通类中的泛型方法
class Test
{
// 把泛型占位符作为参数传入
public void TestFun<T>(T value)
{
Cosnsole.WriteLine(value);
}
public void TestFun2<T>()
{
// default(T) 获取T类型的默认值
T t = default(T);
}
// 泛型作为返回值
public T TestFun2<T>()
{
return default(T);
}
}
2.泛型类中泛型方法
class Test<T>
{
public T value;
// 这个不叫泛型方法,因为T是泛型类在声明的时候就指定了,在使用这个函数的时候就已经确定了
public void TestFun(T t)
{
}
// 泛型方法
public void TestFun<K>(K k)
{
Console.WriteLine(k);
}
}
总结
1.声明泛型时,它只是一个类型占位符
2.泛型真正起作用的时候是在使用它的时候
3.泛型占位字母可以有n个,用逗号隔开
4.泛型占位符一般都是大写字母
5.不确定泛型类型的时获取默认值,可以使用default
6.看到<>包括的字母那肯定是泛型
6.泛型约束
泛型约束概念:
泛型约束角就是让泛型类型有一定限制
关键字:where
泛型约束(6类)
1.值类型 where 泛型字母:struct
2.引用类型 where 泛型字母:class
3.存在无参公共构造函数 where 泛型字母:new()
4.某个类本身或者其派生类 where 泛型字母: 类名
5.某个接口的派生类型 where 泛型字母:接口名
6.另一个泛型类型本身或者派生类型 where 泛型字母:另一个泛型字母
1.值类型约束
class Test<T> where T : struct
{
public T valuer;
public void TestFun<K>(K value) where K : struct
{
}
}
2.引用类型约束
class Test2<T> where T : class
{
}
3.必须存在无参公共构造函数(抽象类不可以)
class Test3<T> Where T : new()
{
}
class Test4
{
}
4.类约束(T必须是类本身或者它的派生类)
class Test5<T> where T: Test1
{
public T value;
public void TestFun<K>(K value) Where K : Test1
{
}
}
class Test6:Test1
{
}
5.接口约束
interface IFly
{
}
class Player:IFly
{
}
class Test7<T> Where T : IFly
{
public T value;
}
6.另一个泛型本身或者派生类型
// T要么和U是一样的,要么是U的派生类
class Test8<T, U> where T : U
{
public T valuer;
public void TestFun1<K,V>(K value) where K : V
{
}
}
static void Main(string[] args)
{
// 值类型约束
Test<int> test1 = new Test<int>();
test.TestFun<int>(10);
// 引用类型约束
Test2<string> test2 = new Test2<string>();
// 必须存在无参公共构造函数
Test3<Test4> test3 = new Test3<Test4>();
// 类约束(T必须是类本身或者它的派生类)
Test5<Test1> test5 = new Test5<Test1>(); // 类自己本身
Test5<Test6> test6 = new Test6<Test6>(); // 类的派生类
// 接口约束
Test7<IFly> test7 = new Test7<IFly>();
// test7.value = new IFly(); // 错误,接口不能new
test7.value = new Player();
// 另一个泛型约束
Test8<Player, IFly> test8 = new Test8<Player, IFly>();
}
泛型约束的组合使用
class Test<T> where T : class, new()
{
}
多个泛型有约束
class Test7<T,K> where T : class, new() where K : struct
{
}
更多推荐


所有评论(0)