C#初级知识——List和Dictionary(一些笔记)
文章目录
前言
初学一些C#的一些知识总结,主要是看擅码网的Monkey老师的3D学习路线第一部分中的《C#初级课程之数据结构》这一块内容。并没有包含所有的知识点讲解,只是记录一些自己觉得应该注意的点。
所有代码均在VS2019中完成。毕竟还是新手,如果有些语句叙述并不严谨到位,还请各位大佬指正。
一、什么是集合结构?
C#中提供了一系列特殊功能的类,这些类可以存储任意类型的对象,并且长度是可变的,他们统称为集合。
在C#语言中,集合结构有两种:泛型集合和非泛型集合。
- 泛型集合,只能存储固定类型的对象的一种集合。
C# 语言中泛型集合是泛型中最常见的应用,主要用于约束集合中存放的元素。 由于在集合中能存放任意类型的值,在取值时经常会遇到数据类型转换异常的情况,因此推荐在定义集合时使用泛型集合。
后面主要讲List集合和Dictionary集合。 - 非泛型集合。它可以存储多种类型的对象,其中最常用的是ArrayList集合和Hashtable集合
二、List集合
1.介绍
List泛型集合是C#编程中的经常使用的集合之一。
List集合的本质是和数组一样,即List集合这个类的内部其实就是维护了一个数组,但是它比数组灵活。List这个类封装了很多能够操作这个内部数组的各种方法,我们可以很方便的对数据进行增、删、改等操作。而且其长度可以动态改变。和数组相比,它也可以动态的添加元素而不是声明的时候就必须指定大小。
2.语法相关
1. 创建List泛型集合
List集合是C#内置的一个类,是类就可以实例化出对象。
首先入引命名空间
using System.Collections.Generic
然后实例化
List<类型> 集合名 = new List<类型>();
2.集合数据操作
相关数据操作即为非常经典的增、删、查、改。
- 增加数据
往集合中添加,数据会不断的添加到集合中,形成一种类似于排队的效果。
集合名.Add(Value)
- 查询数据
List集合的索引和数组,也是从0开始;
也可以通过".Count"来取得
Console.WriteLine(集合名[索引]) //这样就能输出集合中对应的数据
Console.WriteLine(集合名.Count) //这样就能输出集合的长度
- 删除数据
指定索引,并删除索引位置的数据,如果改索引被删除后,该索引后面的数据的索引会动被调整
a = 1;
集合名.RemoveAt(a)
- 修改数据
给定索引,重新复制
集合名[索引] = 新值;
代码如下(示例):
///实例化一个集合
List<int> num = new List<int>();
//添加了一个数据
num.Add(5);
num.Add(15);
num.Add(25);
Console.WriteLine(num[1]);
//读取数据
for (int i = 0;i<num.Count;i++)
{
Console.WriteLine(num[i]);
}
Console.WriteLine("----------");
//删除数据,中间填的是位置
num.RemoveAt(2);
for (int i = 0; i < num.Count; i++)
{
Console.WriteLine(num[i]);
}
//修改数据
num[0] = 100;
Console.WriteLine("----------");
for (int i = 0; i < num.Count; i++)
{
Console.WriteLine(num[i]);
}
代码执行结果如下:
3. List集合管理对象
List集合所能操作的类型,不止常见的string、int等等,还可以是类
下面将展示一段关于List集合管理对象的示例:
- 先添加一个武器类:
① 定义字段id、name、attack(攻击力属性);
② 然后进行属性封装;
③ 再构造含有三个字段的构造方法;
④ 最后改写ToString()方法,使其在调用类名进行输出的时候能够输出武器的相应信息。
class Weapon
{
private int id;
private string name;
private int attack;
public Weapon(int id, string name, int attack)
{
this.id = id;
this.name = name;
this.attack = attack;
}
public int Id { get => id; set => id = value; }
public string Name { get => name; set => name = value; }
public int Attack { get => attack; set => attack = value; }
//改写ToString()方法
public override string ToString()
{
return string.Format("id:{0},name:{1},attack:{2}", this.id, this.name,this.attack);
}
}
- 然后在Program.cs中,进行数据的输出。
(这里夹带了私货,所采用的例子均出自手游《原神》,武器数值均为瞎填,勿究)
class Program
{
static void Main(string[] args)
{
//武器集合的定义
List<Weapon> weapons = new List<Weapon>();
//实例化一把武器,这是一种方式,可以简写
Weapon item = new Weapon(1,"弓藏",510);
weapons.Add(item);
weapons.Add(new Weapon(2, "铁锋针", 165));
weapons.Add(new Weapon(3, "祭礼剑", 56));
weapons.Add(new Weapon(4, "匣里灭辰",201));
//输出一下
for (int i = 0; i < weapons.Count; i++)
{
Console.WriteLine(weapons[i]);
}
//分割线
Console.WriteLine("---------------------");
//按照索引删除
weapons.RemoveAt(1);
//按内容删除,需要遍历集合
for (int i = 0; i < weapons.Count; i++)
{
if (weapons[i].Name == "祭礼剑")
{
//不仅可以删除,也可以修改
weapons.Remove(weapons[i]);
weapons[i].Attack = 31;
}
}
//遍历集合
//直接这样子输出,有18个重载方式
for (int i = 0; i < weapons.Count; i++)
{
Console.WriteLine(weapons[i]);
}
}
}
结果如下:
- 这里要提一下关于Wepon类里面override ToString()方法的问题。如果在Weapon类里面不进行改写的话,输出的结果会变成如下:
可以看到的是,Weapon[i]的输出全变成了项目名+类名。
这个时候,将鼠标放在Program.cs中cw上,会有这样一行字:
因为这样输出会有18个重载,系统默认调用ToString方法来进行输出,就会出现后面那张图的输出。
ToString方法:
① ToString 方法返回一个对象实例的字符串,在默认情况下将返回类类型的限定名。
② C# 中几乎所有的类型都派生自 Object,所以如果当前类型没有重写 ToString() 方法的情况下,调用 ToString() 方法,默认返回当前类型的名称。
③ 任何类都可以重写 ToString 方法,返回自定义的字符串。对于其他的值类型,则为将值转换为字符串类型的值。
这个时候就需要改写一下ToString类,让其输出我们想要的输出:
public override string ToString()
{
return string.Format("id:{0},name:{1},attack:{2}", this.id, this.name, this.attack);
}
之后结果就能正常输出啦!
4.MVC模式
1.MVC介绍
MVC是软件开发行业比较经典的设计模式,那是一种代码开发的思想和套路,将要实现的某个功能分成三个部分:
- V:View[视图层],也就是界面,主要负责和用户进行输入输出的交互;
- C:Controller[控制器层],负责处理该功能的逻辑部分;
- M: Model[模型层],进行数据操作。
可以进一步理解为,V提供可视化界面,C接收用户命令之后,调用各种方法,告诉后台数据应该怎样处理,M按照C的要求处理数据。
以网站登录页面为例进行说明:
登录页面(V)<----> 登录,注册(C)<----> 数据库相关操作(M)
2.代码模式
MVC模式具有三个模式,我们将进行对用户信息的增、删、查、改功能,这里将只放一个框架,具体代码会另开一篇文章具体描述(言外之意就是写的还不完善,哎嘿~)。
- 首先,因为我们对用户进行操作,所有我们需要一个用户类,添加User类:
class User
{
private string name;//用户姓名
private int age;//用户年龄
private string address;//用户地址
///无参的构造函数
public User(){}
///有参的构造函数
public User(string name, int age, string address)
{
this.name = name;
this.age = age;
this.address = address;
}
//对字段进行封装
public int Name{ get => name; set => name = value; }
public int Age { get => age; set => age = value; }
public string Address { get => address; set => address = value; }
//改写ToString方法
public override string ToString()
{
return string.Format("{0}|{1}|{2}", this.name, this.age,this.address) ;
}
}
- User类创建好了之后,我们还需要一个一个控制器,UserController类。
这边将只放出框架,各个方法内部都是调用List集合的方法,或者还进行一些数据的筛选以及为了增强程序的健壮性而进行的逻辑判断。详细会在另一篇放出。
class UserControler
{
//实例化一个用户集合
List<User> userList = new List<User>();
/// 上面的集合是内部的一个数据集合,是不能对外公布的,即使是再简单的操作,也用public进行封装
/// <summary>
/// 添加数据
/// </summary>
/// <param name="user"></param>
public void AddItem(User user) {}
//删除数据
//删除数据将使用两种删除方法
//一种是按地址删除,一种是按用户名字删除
/// <summary>
/// 按用户名字删除
/// </summary>
public void RemoveName(string name){ }
/// <summary>
/// 按用户地址删除数据
/// </summary>
public void RemoveAddress(string address){ }
//修改数据
public void AlterInfo(string name,string address) { }
//查找数据
public void ShowAll() { }
}
- 同样的,提供给用户交互界面的视图层,同样也只提供一个框架。
/// <summary>
/// 视图层
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Console.WriteLine("----------------------");
Console.WriteLine("-----用户管理系统-----");
Console.WriteLine("----------------------");
Console.WriteLine("1.添加用户信息");
Console.WriteLine("2.修改用户信息");
Console.WriteLine("3.删除用户信息");
Console.WriteLine("4.查看用户信息");
Console.WriteLine("5.退出系统");
//需要实例化一个UserController控制器对象
UserControler uc = new UserControler();
#endregion
while (true)
{
Console.Write("请选择你需要执行的功能:");
//接受用户输入的数据
string userInput = Console.ReadLine();
//对用户输入的数据进行判断
switch (userInput)
{
case "1":
{
//姓名
string n = Console.ReadLine();
//年龄
int a = Convert.ToInt32(Console.ReadLine());
//地址
string ad = Console.ReadLine();
//调用控制器中的方法,将数据添加进集合
uc.AddItem(new User(name, age, address));
}
break;
case "2":
{
string nA = Console.ReadLine();;//需要查找的名字
string adAlter=Console.ReadLine();//需要修改成的地址
uc.AlterInfo(nA, adAlter);
}
break;
case "3":
{
//按姓名删
string nameInputRemove = Console.ReadLine();
uc.RemoveName(nameInputRemove);
//按地址删
string addressInputRemove = Console.ReadLine();
uc.RemoveName(addressInputRemove);
break;
}
break;
case "4":
uc.ShowAll();
break;
case "5":
break;
default:
Console.WriteLine("您输入的格式不对,请重新输入QvQ!");
Console.WriteLine();
break;
}
}
}
3. Dictionary介绍
1. Dictionary集合介绍
Dictionary集合是一种“键值对”集合,它包含在System.Collections.Generic名空间中:
-
从一组键(Key)到一组值(Value)的映射,每一个添加项都是由一个值及其相关连的键组成
-
任何键都必须是唯一的
-
键不能为空引用null(VB中的Nothing),若值为引用类型,则可以为空值
-
Key和Value可以是任何类型(string,int,custom class 等)
2. Dictionary集合的基本使用
1. 创建Dictionary泛型集合
- 首先映入命名空间:
using System.Collections.Generic
; - 创建集合
Dictionary<K类型,V类型> 集合名 = new Dictionary<K类型,V类型>();
2. 集合数据操作
-
增加数据
往集合中添加数据,由于Dictionary的键是唯一的,不能添加两个同键名的数据。
集合名.Add(K,V)
-
查询数据
取出指定键名对应的数据,以及获取集合的长度。 信息
xxx = 集合名[键名]
yyy = 集合名.Count
-
修改数据
给指定键名所对应的数据重新赋值。
集合名[键名] = 新值;
-
删除数据
删除指定键名所对应的数据。
集合名.Remove(键名)
-
遍历字典
字典没有角标,是通过键来索引的,所有选择用foreach
foreach (var item in dic.Keys)
{
Console.WriteLine("{0}:{1}",item,dic[item]);
}
3. Dictionary 常用方法
-
判断当前字典集合中是否包含某个键,返回bool值。
ContainsKey(K)
-
判断当前字典集合中是否包含某个值,返回bool值。
ContainsValue(V)
示例代码如下:
4. 选择一个类MVC模式,来管理电话本,添加一个phoneController类
/// <summary>
/// C.控制器
/// </summary>
class PhoneController
{
//定义一个字典集合<姓名,电话号码>
Dictionary<string, string> phones = new Dictionary<string, string>();
//增
/// <summary>
/// 添加数据
/// </summary>
/// <param name="name">姓名</param>
/// <param name="phoneNumber">电话号码</param>
public void AddItem(string name,string phoneNumber)
{
phones.Add(name, phoneNumber);
}
//删
/// <summary>
/// 通过名字删除号码
/// </summary>
/// <param name="name">姓名</param>
public void DelItem(string name)
{
phones.Remove(name);
}
//查
/// <summary>
/// 显示所有的字典信息
/// </summary>
public void ShowAll()
{
foreach (var item in phones.Keys)
{
Console.WriteLine("{0}:{1}",item,phones[item]);
}
}
//改
public void UpdateItem(string name,string number)
{
phones[name] = number;
}
//判断键是否存在
public void SearchKeys(string name)
{
if (phones.ContainsKey(name))
{
Console.WriteLine("{0}这个键存在!", name);
}
else
{
Console.WriteLine("{0}这个键不存在!", name);
}
}
//判断值是否存在
public void SearchValues(string number)
{
if (phones.ContainsValue(number))
{
Console.WriteLine("{0}这个值存在!", number);
}
else
{
Console.WriteLine("{0}这个值不存在!", number);
}
}
}
- 在Program.cs中
class Program
{
/// <summary>
/// view视图类
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
PhoneController pc = new PhoneController();
//添加
pc.AddItem("达达利亚", "11111111");
pc.AddItem("胡桃", "22222222");
//查询
pc.ShowAll();
Console.WriteLine("------------------------");
//更改
pc.UpdateItem("胡桃", "333333333");
//删除
pc.DelItem("胡桃");
pc.ShowAll();
Console.WriteLine("------------------------");
//判断键是否存在
pc.SearchKeys("达达利亚");
pc.SearchKeys("胡桃");
//判断值是否存在
pc.SearchValues("11111111");
pc.SearchValues("22222222");
Console.ReadKey();
}
}
代码执行结果如下:
总结
简单学习了List和Dictionary集合的使用,关于MVC用户管理系统详细的写法会另开一个文档。
之后也将继续学习C#的其他数据结构,如链表,队列,栈,二叉树,图等等。