C#OPP入门
第一章 深入.NET框架
一 、 .NET框架体系结构
1.NET框架的结构
.NET框架也就是.NET FrameWork,主要包含公共语言运行时(CLR)和框架类库(FCL)。CLR包含两个组成部分:
CTS:通用类型系统,如C#中的整型是int,而VB.NET中的整型是Integer,通过CTS我们把它们两个编译成通用的类型Int32。
CLS:公共语言规范,如在C#中命名是区分大小写的,而在VB.NET中不区分大小写,这样CLS就规定,编译后的中间代码除了大小写之外还要有其他的不同之处。
MSIL:中间语言,vs统一能认识的规范语言。
FCL:框架类库,有些已经被封装好的功能的集合。
二、类和对象
1.类和对象的概念
类: 具有相同特性和行为的对象组成的集合就是类,实际上类就是一个数据类型。
对象:一个具体存在的实物,世间万物皆为对象。
2.类和对象的关系:
类是对象的抽象化,对象是类的实例化。
public class Student{} //这是一个学生类
static void Main(string [] args)
{
Student s1=new Student(); //类的实例化-->对象
}
3.类的成员:
字段:一般把类或结构中定义的变量和常量叫字段,建议私有化。
属性:get只读属性,set只读属性,可以同时拥有,也可以只存在其中一个。
方法:语法:访问修饰符 返回值类型 方法名(参数列表){}
public class Student
{
private string _name; //字段
public string Name { get => _name; set => _name = value; } //属性
//方法
public void SayHi(){}
}
分为两种:
静态方法:使用static关键字来标识静态方法。
非静态方法:同样,非静态方法就是不使用static关键字修饰。
区别:1.静态方法不能调用非静态方法。
2.调用:静态方法只能通过类名点方法名来访问,不能通过对象名点方法名访问。
非静态方法的调用可以通过对象名点方法名访问。
public class Employee
{
public static void SayHi(){}
public void ShowHobby(){}
static void Main(string [] args)
{
Employee.SayHi(); //静态方法通过类名点方法名调用
//Employee.ShowHobby(); //会报错,静态方法不能调用非静态方法
Employee e1 =new Employee();
e1.ShowHobby(); //非静态方法的调用可以通过对象名点方法名访问。
}
}
①访问修饰符
public:公开的,人人都能使用。
protected:受保护的,在继承中,一般用于父类,类的受保护成员只能由类本身和类的子类内部访问,相当于有密码的WiFi。
private:私有的,只能在类内部使用,相当于自己的流量。
类的默认访问修饰符:internal
类成员的默认访问修饰符:private
②返回值类型:数据类型+void
void:void表示方法没有返回值,这时注意不能用return返回值。
数据类型:return必须存在,而且必须有值,值的类型必须和返回值类型兼容。
③参数:分为两种:
形参:定义方法时传入的参数,形参是抽象的。
实参:调用方法时传入的参数,实参的数据类型必须和形参一致,参数个数、顺序也相同。
public void Swap(){}
Swap(); //调用
public void Swap1(int a){}
Swap1("1"); //报错,实参形参数据类型不一致
Swap1(1);
public void Swap2(int a,int b){}
Swap2(1); //报错,实参和形参数目不同
Swap2(1,2);
4.类的三大特性:
封装:将类内部构造私有化。
继承:子类继承父类。
多态:在同一范畴内,一个事物有多种形态。
第二章 深入C#数据类型
一 、值类型和引用类型
1.值类型
<1>、命名空间:System.ValueType;
<2>、保存区域:每个值类型的对象都有一个独立的内存区域用于保存自己的值,值类型数据所在的内存区域称为栈,值变地址也变,一个字段占用一个栈;
<3>、包括基本数据类型、枚举类型(enum)、结构类型(struct);
2.引用类型
<1>、命名空间:System.Object;
<2>、保存区域:引用类型存储对值的引用,数据所在的内存区域称为堆,值变地址不变,字段怎么改变也是原来的地址;
<3>、包括类、接口、数组
3.区别:
值类型:不同的变量分配不同的储存空间,一个变量的值改变不会影响另外一个变量。 //指向栈 开辟了新地址
引用类型:不同的变量分配相同的储存空间,一个引用类型的值改变也会影响另一个变量。//指向了堆 使用了原来的地址。
int heightZhang = 170;
int heightLi =heightZhang;
heightLi=180;
//int是值类型,首先系统会给heightZhang分配存储空间,然后系统还会给heightLi分配存储空间,所以改变heightLi的值不是影响heightZhang的值
int [] array = new int [5];
int []array1=array; //这里把array的引用地址也给了array1,所以array1指向的地址和array一样,array1的值变,array的值也会变
int [] array=new int[5]
int [] array1=new int[5] //array1开辟了一个新的空间
array1[0]=array[0]; //因为array1开辟了新的空间,而且这里是给的下标值,所以array1的值变array的值不会随着改变,因为指向的地址不同
二、结构
1、结构的定义:
访问修饰符 struct 结构名{}
2、结构的特点:
①结构中可以有字段,也可以有方法,但是很少写属性;
②定义时,结构中的字段不能被赋初始值
3、结构的使用:
①可以不用new,直接定义结构的对象即可;
②声明结构的对象后,必须给结构的成员赋初始值。
4、注意:①结构不能不支持继承;
②在没有new的时候,不能定义属性,并且不能调用方法;
③结构的构造函数必须是有参数构造函数;
④结构和类相似,但是结构属于值类型,而类属于引用类型。
//例如
public struct Student
{
public int _id; //字段
public int _age; //不能赋初始值
public void Study(){}
static void Main(string [] args)
{
Student stu;
stu._id=111;
stu.Study(); //报错,在没有new时候不能调用方法
}
}
三、装箱和拆箱
1、装箱:将值类型转换成引用类型
2、拆箱:将引用类型转换成值类型
四、参数传递
1、值方式参数传递
值方式参数传递就是没有ref关键字修饰,参数可以是引用类型,也可以是值类型。
①使用引用类型作为参数
class Program
{
static void Main(string[] args)
{
Number a = new Number();
Add(a);
Console.WriteLine(a.i);
Console.ReadLine();
}
static void Add(Number a)
{
a.i++;
}
}
class Number
{
public int i = 10;
}
//输出结果 :11
以上代码可以看出,以引用类型作为参数进行值方式传递参数时,会改变引用类型参数的值。
②使用值类型作为参数
static void Main(string[] args)
{
//值传递
int number = 20;
Fun(number);//实参
Console.WriteLine(number);
Console.ReadLine();
}
static void Fun(int num)//形参,值类型作为参数
{
num += 20;
}
//输出结果:20
以上代码可以看出,以值类型作为参数进行值方式传递参数时,不能改变值类型参数的值。
2.引用方式参数传递
引用方式参数传递就是有ref关键字修饰,参数同样可以是引用类型,也可以是值类型。
①使用值类型作为参数
static void Main(string[] args)
{
int number = 20;
Fun(ref number);//实参
Console.WriteLine(number);
}
static void Fun(ref int num)//形参
{
num += 20;
}
//输出结果:40
class Program
{
static void Main(string[] args)
{
Number a = new Number();
Add(ref a);
Console.WriteLine(a.i);
Console.ReadLine();
}
static void Add(ref Number a)
{
a.i++;
}
}
class Number
{
public int i = 10;
}
//输出结果 :11
以上代码可以看出,使用引用方式(用ref关键字修饰)传递值类型和引用类型参数时,参数在方法中的修改都会保留。注意,在引用方式参数传递时,实参和形参的前面都必须加上ref关键字。
第三章 使用集合组织相关数据
一、ArrayList
1.ArrayList的定义:ArrayList非常类似于数组,可以保存一组大小不固定、数据类型不相同的数据的集合。
注意:由于ArrayList不限定数据类型,所以经常涉及数据类型转换、拆箱、装箱,这是ArrayList的优势同样也是劣势。
2.命名空间:System.Collections
3.如何创建ArrayList?
ArrayList list =new ArrayList();
4.ArrayList的属性和方法
属性:Count 说明:获取ArrayList的长度
返回值类型 | 方法名称 | 说明 |
---|---|---|
int | Add(Object value) | 添加元素,用来保存值 |
void | RemoveAt(int index) | 通过下标删除元素,下标从0开始,最后一个值的下标:长度-1 |
void | Remove(Object value) | 通过指定元素直接删除 |
void | Clear() | 清空ArrayList中的数据 |
//例如
ArrayList list =new ArrayList(); //创建ArrayList集合
list.Add("悠悠"); //下标为0
list.Add(17); //存值 //1
list.Add('女'); //2
Console.WriteLine(list.Count); //打印长度 输出:3
list.Remove("悠悠"); //删除指定元素
list.RemoveAt(2); //运行报错,因为在这之前删除了“悠悠”,所有元素都会向前移,因此不存在下标为2的元素
list.Clear(); //清空
Console.WriteLine(list.Count); //打印长度 输出:0
5.ArrayList的遍历
//for循环
for(int i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
//foreach循环
foreach(Object obj in list)
{
Console.WriteLine(obj)
}
二、List
1.定义:保存一组大小不固定,但限定数据类型的数据的集合。
2.命名空间:System.Collections.Generic
3…创建:List list =new List(); T就是Type类型的意思,表示任意一种数据类型
4.List的属性和方法
属性:Count 说明:获取ArrayList的长度
返回值类型 | 方法名称 | 说明 |
---|---|---|
int | Add(T value) | 添加元素,当newList的时候T是什么数据类型,就只能添加什么数据类型 |
void | RemoveAt(int index) | 通过下标删除元素,下标从0开始,最后一个值的下标:长度-1 |
void | Remove(T value) | 删除指定的元素 |
void | Clear() | 清空集合中的元素 |
List<string> list =new List<string>();
list.Add(666); //报错,T为string类型,666是int类型,数据类型不一致
list.Remove("你好"); //不报错,虽然我没添加到集合中,但是无影响!!!
//注意:当移除一个不存在的值,其实不会有任何错误。
5.List的遍历
//for循环
for(int i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
//foreach循环
foreach(T item in list)
{
Console.WriteLine(item)
}
三、ArrayList和List的区别
1.相同点:
①相同的属性:Count
②相同的方法:Add,Remvoe,RemoveAt,Clear
③相同的遍历方式
2.不同点:
①List对储存的元素类型进行约束,添加/读取值类型元素无需拆箱、装箱
②ArrayList可以添加任何类型的元素,添加/读取值类型元素需要拆箱、装箱
四、HashTable
1.定义:用来保存key:value,大小不固定,并且可以添加任意数据类型的元素。
2.命名空间:System.Collections
3.创建:HashTable ht=new HashTable();
4.HashTable的属性和方法
属性名称 | 说明 |
---|---|
Count | 获取HashTable的长度 |
Keys | 获取包含在HashTable中键的集合 |
Values | 获取包含在HashTable中值的集合 |
返回值类型 | 方法名称 | 说明 |
---|---|---|
void | Add(Object key,Object values) | 添加元素 |
void | Remove(Object key) | 删除指定的key |
void | Clear() | 清空元素 |
bool | ContainsKey(Object key) | 查找指定的key是否已经存在 |
bool | ContainsValue(Object key) | 查找指定的value是否已经存在 |
HashTable ht =new HashTable();
ht.Add(17,"悠悠"); //键是学号,值是姓名
ht.Add(01,"喵喵");
ht[01]="菜菜"; //修改值,前提必须存在
5.HashTable遍历
//遍历key
foreach(Object obj in ht.Keys)
{
Console.WriteLine(obj+"----"+ht[obj]); //通过key获取值
}
//遍历value
foreach(Object item in ht.Values)
{
Console.WriteLine(item) //直接获取值
}
//同时获得key和value
foreach(DictionaryEnary en in ht )
{
Console.WriteLine(en.Key+"----"+en.Value)
}
注意:1、key如果已经存在了,再次添加,会报运行错误,说明key不能重复
2、null不能作为key
五、Dictionary
1.定义:用来保存key:value,大小不固定,但是限定数据类型的数据的集合。
2.命名空间:System.Collections.Generic
3.创建:Dictionary<Tkey,Tvalue> dic =new Dictionary<Tkey,Tvalue>();
4.Dictionary的属性和方法:和Hashtable一样
5.Dictionary遍历
//遍历key和遍历value和HashTable一样
//同时遍历key和value
foreach(KeyValuePair en in dic)
{
Console.WriteLine(en.Key+"----"+en.Value)
}
六、Hashtable和Dictionary的区别
1.相同点:
①相同的属性:Count,Keys,Values;
②相同的方法:Add,Remvoe,Clear,ContainsKey,ContainsValue;
③相同的遍历方式
2.不同点:
①Hashtable没有限定类型;
②Dictionary限定了key和value的数据类型
Dictionary<string,string> dic =new Dictionary<string,string>();
dic.Add("17","悠悠");
dic.Add(01,"菜菜"); //编译错误,Dictionary中的键是string类型的,01是int类型,数据类型不一致
dic.Add(null,"明明"); //运行错误,null不能作为键
dic.Add("01","菜菜");
foreach(string en in dic.Keys)
{
Console.WriteLine(en+"----"+ht[en]); //通过key获取值
}
bool flag=dic.ContainsKey(02); //查找集合中是否已经存在02键,存在返回true,不存在返回false
七、泛型和非泛型的区别
泛型:限制了数据类型,比如List和Dictionary。
非泛型:没有限制数据类型,比如ArrayList和Hashtable.
八、自定义泛型类
1、泛型类的作用是将类中的属性进行限制;
2、语法:public class 类名{}
public T name; //属性
当你实例化对象时:
类名 对象名 = new 类名();
此时进入的是什么类型,类中的属性就是什么类型.
九、集合绑定dgv
1.Lis绑定dgv:this.dgv.DataSource=new BindingList();
2.Dictionary绑定dgv:
BindingSource bs =new BindingSource();
bs.DataSource=dic.Values;
this.dgv.DataSource=bs;
注意:使用Datagridview绑定集合
这里的属性需要加:{get;set;}才能绑定成功!
例如:
public string name { get; set; }
public string id { get; set; }
第四章 深入类的方法
一、构造函数
1.语法:访问修饰符 类名(){}
注意:①类似方法,只是少了一个返回值,这里是没有返回值,若为void也是错误的,void代表返回值类型为空;
②方法名有要求:跟类名一致;
③构造函数也是会被重载。
2.作用:用来new对象,兼职:给成员变量赋值
3.分类:
①显示方式:
隐式:
1、就是创建一个类,没有手写构造函数的时候当前类自带的构造函数
2、就是无参的构造函数
显示:自定义构造函数
②参数的格式:有参和无参
4.特点:一个类中,如果没有手写的构造函数,那么这个类中有一个隐藏的无参构造函数,如果一旦手写了构造函数,那么这个类就不存在有隐藏的构造函数。
5.给成员变量赋值的方式:
①对象初始化器
static void Main(string[] args)
{
//对象初始化器赋值
Student stu = new Student(){name="悠悠",age=18};
}
class Student
{
public string name;
public int age;
}
②点符号
static void Main(string[] args)
{
//点符号赋值
Student stu = new Student();
stu.name="悠悠";
stu.age=18;
}
class Student
{
public string name;
public int age;
}
③构造函数
static void Main(string[] args)
{
//构造函数赋值
Student stu = new Student("悠悠",18); //调用Student类中的有参构造函数
}
class Student
{
public string name;
public int age;
public Student(){} //无参构造函数
public Student(string name,int age)
{
this.name=name;
this.age=age;
}
}
二、方法重载
1.实现多态的方式:①重载②重写
2.特点(定义):在同一个类中,方法名相同,对应的参数的下标参数类型不同。
3.重载的应用:MessageBox,Equals(可以尝试去看源代码,深入理解重载)
4.存在的意义:减少方法名的开辟,同样避免我们本身英语单词不足这一问题。
5.调用规则:根据参数【参数个数+数据类型】调用
6.注意:
不能以【返回值类型】来决定是否是重载
不能以【访问修饰符】来决定是否是重载
//方法重载的使用
static void Main(string[] args)
{
Calc c1=new Calc();
Console.WriteLine(c1.Pay(1, 9)); //输出:10
Console.WriteLine(c1.Pay(1.1, 5.9)); //输出:7
Console.WriteLine(c1.Pay("你好,", "世界")); //输出:你好,世界
Console.ReadLine();
}
class Calc
{
public Calc(){}
public int Pay(int a,int b)
{
int sum =a+b;
return sum;
}
public double Pay(double a,double b)
{
double sum =a+b;
return sum;
}
public string Pay(string a,string b)
{
string sum =a+b;
return sum;
}
}
上一篇: opp基础,继承
下一篇: xshell怎么远程连接linux