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的长度

返回值类型方法名称说明
intAdd(Object value)添加元素,用来保存值
voidRemoveAt(int index)通过下标删除元素,下标从0开始,最后一个值的下标:长度-1
voidRemove(Object value)通过指定元素直接删除
voidClear()清空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的长度

返回值类型方法名称说明
intAdd(T value)添加元素,当newList的时候T是什么数据类型,就只能添加什么数据类型
voidRemoveAt(int index)通过下标删除元素,下标从0开始,最后一个值的下标:长度-1
voidRemove(T value)删除指定的元素
voidClear()清空集合中的元素
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中值的集合
返回值类型方法名称说明
voidAdd(Object key,Object values)添加元素
voidRemove(Object key)删除指定的key
voidClear()清空元素
boolContainsKey(Object key)查找指定的key是否已经存在
boolContainsValue(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;
    }
}

第六章 初识继承和多态

一、继承

1.概念:描述两个类之间的关系,子类是继承的类,子类又叫派生类,父类是被继承的类,父类又叫基类或者超类。

2.语法:访问修饰符 class 子类:父类

3.访问修饰符:

public:公共的、公开的

protected:受保护的,被这个访问修饰符修饰的成员允许被其子类访问,而不允许其他非子类访问。

private:私有的,只能在类的内部使用。

注意:一旦产生继承关系,子类可以访问所有父类非私有成员。

4.构造函数

所有子类的构造函数都会调用父类的构造函数,默认情况下调用父类的无参构造函数,也可以显示的调用父类的构造函数。使用base关键字:

在子类的构造函数括号外使用:base()则表示显示调用父类的无参构造函数。

:base(值)则表示显示调用父类的有参构造函数。

注意:使用base调用父类的有参构造函数时,()里面的值是实参,而不是形参!

public class Person
{
    public string Name{get;set;}
    public int Age{get;set;}
    //构造函数
    public Person(){}
    public Person(string name,int age)
    {
        this.Name=name;
        this.Age=age;
    }
}

//子类
public class Student:Person
{
	public string Hobby{get;set;}
	public Student():base(){}   //显示调用父类无参构造函数,没什么意义:因为默认情况下子类会调用父类的无参构造函数
	public Student(string name,int age,string hobby):base(name,age)//显示调用父类的有参构造函数
	{
		this.Name=name;
		this.Age=age;
		this.Hobby=hobby;
	}
}

注意:一旦手写了构造函数,那么这个类就不存在有隐藏的无参构造函数。所以当子类调用父类的构造函数时,一定要看清楚父类的构造函数!

5.base和this的区别

this是指当前类的成员的引用;base是指在当前类中调用父类的成员。

6.继承的特性:

①单根性:每一个类都只能有一个父类;

②传递性:孙子可以拥爷爷辈的基因

注意:每一个类如有没有显示定义父类,都有一个默认的父类:Object;如果某一个类想禁止被继承,在class前面使用关键字:sealed(密封类)

7.is和as

is a是判断对象是否属于给定的数据类型,返回布尔类型,如果属于返回true,否则返回false。

语法:引用名[对象名] is 数据类型;

as a是用来强制转换

语法:数据类型 变量名 = 对象名 as 数据类型;

等价于 数据类型 变量 = (数据类型)对象名;

public class Employee
{
    public void SayHi()
    {
        Console.WriteLine("大家好!");
    }
}

public class SE:Employee
{
	Console.WriteLine("大家好!我是员工");
}
public class PM:Employee
{
	Console.WriteLine("大家好!我是经理");
}

static void Main(string [] args)
{
    List<Employee> empls =new List<Employee>();
    //省略初始化代码
    foreach(Employee emp empls)
    {
        if(emp is SE)
        {
            SE se =emp as SE;
            Console.WriteLine(se.SayHi());
        }
        if(emp is PM)
        {
            PM pm =emp as PM;
             Console.WriteLine(pm.SayHi());
        }
    }
}

二、多态

1.概念:在同一范畴中,一个事物的多种形态。

2.实现多态的方式:重载和重写。

3.重写:
1.前提:继承关系

​ 2.特点:在不同的类中,相同的方法名和相同的参数,返回值类型也相同,但是方法体不同。

​ 3.标注方式:①虚方法;②抽象方法

4.虚方法:

①实现方式:父类的方法用关键字virtual修饰,子类将重写的方法使用override关键字。

②注意:父类的方法必须有方法体

public class Person
{
    public Person(){}
    public virtual void SayHi()
    {
        Console.WriteLine("大家好!");
    }
}

//子类
public class Student:Person
{
	public int ID{get;set;}  //学号
    public Student(){}
    public override void SayHi()
    {
    	Console.WriteLine("大家好!我的学号是{0}",this.ID);
    }
}

第七章 深入理解多态

一、里氏替换原则

1.里氏替换原则的概念:所有引用父类的地方,都可以透明的使用子类对象。

2.继承的优点:①提供了代码的重用性,子类拥有父类的属性和方法;

②提供了代码的可扩展性,子类可以形似父类,也异于父类保留自我个性。

3.继承的缺点:①继承侵入式编程【子类拥有父类的属性和方法】

只要有继承关系,父类里面所有动作子类也一定有,实际上父类约束了子类的行动。

②增加了耦合性

二、抽象类和抽象方法

1.抽象类:

①语法:访问修饰符 abstract class 类名{}

②抽象类的特点:不能实例化对象,抽象类不能使用sealed和static修饰,抽象类中可以有抽象方法也可以有非抽象的方法。

2.抽象方法:

①定义:访问修饰符 abstract 返回值类型 方法名(参数列表){}

②特点:在不同的类中,方法名相同和参数相同,返回值类型也相同,抽象方法没有方法体,并且只能位于抽象类中,父类里面的抽象方法子类必须实现,除非子类也是抽象的。

③实现方式:前提在抽象中,父类的方法用关键字abstract修饰,子类被重写的方法使用关键字override修饰。

3.存在的意义:规定子类必须重写父类的方法。

//父类:动物类
public abstract  class Animal
{
    //抽象方法
    public abstract void Eat();
}

public class Monkey:Animal
{
	//子类必须重写父类的方法
	 public override void Eat()
     {
     	Console.WriteLine("猴子吃香蕉!");
     }
}

三、虚方法和抽象方法的区别

1.相同点:都是在约定子类拥有某个动作

虚方法:只能约定子类的动作可以是父类实现的。

抽象方法:只能子类自己实现,因为抽象方法没有方法体。

2.不同点:

不同点定义关键字不同方法体的要求对类要求的不一样(密封类除外)对子类的实现不一样
虚方法virtual必须有方法体可以位于任意类不强制要求子类必须实现
抽象方法abstract不能有方法体只能位于抽象类子类必须实现,除非子类也是抽象

四、软件设计原则

1.里氏替换原则:父类的引用指向子类的对象

2.单一职责原则:一个类只做一件事

3.依赖倒置原则:细节依赖抽象,而不是抽象依赖于细节

4.接口隔离原则:接口:只有抽象方法,

5.开闭原则:对修改关闭,对扩展开放

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值