①访问限制
- public:所有类均可使用
- internal:同一命名空间(程序集)中的类可以使用
- protected:在本类中及其子类中可以使用
- private:只能在本类中使用,默认。
从上到下,访问限制逐渐升高
②using用法
- 引入命名空间
- 定义别名
- 定义临时块范围,在该范围结束时回收资源。
③new用法
- 用作运算符:创建对象和调用构造函数。
- 用作修饰符:隐藏从基类继承的属性、字段、方法(因为不能删除,所以选择隐藏),用于关闭警告。
- 用作约束:在泛型声明中约束可能用作类型参数的参数类型。
④常用快捷键
- 进入MSDN/查看帮助:F1
- 启动调试:F5,直接运行:Ctrl+F5
- 试图转向代码:F7,代码转向试图:Ctrl+F7
- 设置/取消断点:F9
- 单步调试:F10
- 逐句调试:F11
- 转到定义处:F12
⑤重载、重写、覆盖
- 重载指的是同一个类中有两个或多个名字相同但是参数个数、次序、类型不同的方法,(注:返回值可相同可不同),重载没有关键字。
- override:重写是指子类对父类中虚函数或抽象函数的“覆盖”,实现新的功能,它必须和父类方法的方法名、参数、返回类型、访问修饰符完全一致。但是这种“覆盖”和用new关键字来覆盖是有区别的,通过指向子类的父类对象不能调用到被重写的父类方法,但父类对象本身仍可以调用到父类方法。
- new:覆盖指的是不同类中(基类或派生类)有两个或多个返回类型、方法名、参数都相同,但是方法体不同的方法。但是这种覆盖是一种表面上的覆盖,所以也叫隐藏,通过指向子类的父类对象可以调用到被重写的父类方法,父类对象本身当然也可以调用到父类方法。
综上:
- 重载,必然发生在一个类中,函数名相同,参数类型或者顺序不同构成重载,与返回类型无关
- 重写,必然发生在基类和派生类中,基类函数用virtual或abstract修饰,派生类用override修饰
- 覆盖,在子类中写一个和基类一样名字(参数不同也算)的非虚函数,会让基类中的函数被隐藏,编译后会提示要求使用New关键字
⑥结构struct与类class的区别
1. 值类型与引用类型
结构是值类型:值类型在堆栈上分配地址,所有的基类型都是结构类型,例如:int 对应System.int32 结构,通过使用结构可以创建更多的值类型
类是引用类型:引用类型在堆上分配地址 ,例如string
堆栈的执行效率要比堆的执行效率高,可是堆栈的资源有限,不适合处理大的逻辑复杂的对象。所以结构处理作为基类型对待的小对象,而类处理某个商业逻辑
因为结构是值类型,所以结构之间的赋值是创建新的结构,而类是引用类型,类之间的赋值只是复制引用
注:
a.虽然结构与类的类型不一样,可是他们的基类型都是对象(object),c#中所有类型的基类型都是object
b.虽然结构的初始化也使用了New 操作符可是结构对象依然分配在堆栈上而不是堆上,如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用
2.继承性
结构:不能从另外一个结构或者类继承,本身也不能被继承,虽然结构没有明确的用sealed声明,可是结构是隐式的sealed .
类:完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也能被继承
注:虽然结构不能被继承,可是结构能够继承接口,方法和类继承接口一样
3.内部结构:
结构:
没有默认的构造函数,但是可以添加构造函数 (结构体中不能定义默认的、不带参数的构造函数,只能定义带参的构造函数)
没有析构函数
没有 abstract 和 sealed(因为不能继承)
不能有protected 修饰符
可以不使用new 初始化
在结构中初始化实例字段是错误的
类:
有默认的构造函数 (可以定义默认的、不带参数的构造函数,或者带参的构造函数)
有析构函数
可以使用 abstract 和 sealed
有protected 修饰符
必须使用new 初始化
⑦实例化过程、this、base
1)先不考虑继承关系,执行顺序为:
静态字段
静态构造方法
实例字段
实例构造方法
2)考虑继承关系,执行顺序为:
子类的静态字段
子类的静态构造方法
子类的实例字段
父类的静态字段
父类的静态构造方法
父类的实例字段
父类的实例构造方法
子类的实例构造方法
3)this关键字
this关键字代表当前对象,通过this关键字可以访问当前对象的成员。(当前对象的成员:自己本身的成员+从父类继承过来的所有的成员。)
this关键字可以访问:本类的所有成员和父类的非私有成员。父类的私有成员确实存在,但是就是访问不到。
this关键字仍然代表的是对象,通过它可以点出对象中的除了父类的私有成员以外的所有成员。
this关键字只能用在实例方法中。
作用:
1)代表当前对象。在实例方法中使用this关键字就代表当前对象。通过this关键字可以点出本类的所有成员和父类的非私有成员。
2)调用本类的其他的构造函数。在构造函数的后面的this代表调用本类的其他的构造函数。
4)base关键字
显示的访问父类的非私有成员。可以访问子类对象中的父类的非私有成员。base不代表父类对象。因为压根就没有父类对象。通过它可以访问到父类的非私有成员。通过this关键字访问当前对象的成员的时候:先找子类本身有没有这个成员,如果没有再找是否有从父类继承过来的。base关键字 直接就找父类中的成员。我们发现,base可以点出来的成员,通过this都可以点出来访问。
建议:如果我们访问的确实是从父类继承过来的,那么建议用base关键字访问,这样方便代码的阅读和提高效率。只有在访问的成员确实是子类独有的,那么我们才用this关键字。
作用:
1)在实例方法中,通过base关键字可以显示的访问子类对象中的非私有的父类成员。
2)调用父类的构造函数。在子类的构造函数的后面的base代表调用父类的构造函数。
⑧抽象类abstract,接口interface,密封类sealed
1)abstract修饰符可以和类,方法,属性,索引及事件一起使用。
在类声明时使用abstract修饰符,以指示该类只能是其他类的基类,标记为抽像或包含在抽像类中的成员必须在抽像类的派生类中实现;
抽象类特性:
抽像类不能实例化。
抽像类可以包含抽象方法和抽像访问器。
不能用sealed修饰符修改抽像类。
抽像方法特性:
是隐式的virtual方法。
只能在抽像类中使用抽像方法声明。
不提供实际的实现。
具体实现由override方法提供,它是非抽像类的成员。
使用static或virtual修饰符是错误的。
即:abstract是一种抽象,好比上帝,是人们对神的抽象,看似什么都能做,其实什么都做不了。
2)接口的定义:
接口的定义是指定一组函数成员而不实现成员的引用类型,其它类型和接口可以继承接口。
接口主要有以下特点:
1)通过接口可以实现多重继承,C#接口的成员不能有public、protected、internal、private等修饰符。原因很简单,接口里面的方法都需要由外面接口实现去实现方法体,那么其修饰符必然是public。C#接口中的成员默认是public的,java中是可以加public的。
2)接口成员不能有new、static、abstract、override、virtual修饰符。有一点要注意,当一个接口实现一个接口,这2个接口中有相同的方法时,可用new关键字隐藏父接口中的方法。
3)接口中只包含成员的签名,接口没有构造函数,所有不能直接使用new对接口进行实例化。接口中只能包含方法、属性、事件和索引的组合。接口一旦被实现,实现类必须实现接口中的所有成员,除非实现类本身是抽象类。
4)C#是单继承,接口是解决C#里面类可以同时继承多个基类的问题。
3)接口和抽象类的区别:
接口用于规范,抽象类用于共性。抽象类是类,所以只能被单继承,但是接口却可以一次实现多个。
接口中只能声明方法,属性,事件,索引器。而抽象类中可以有方法的实现,也可以定义非静态的类变量。
抽象类可以提供某些方法的部分实现,接口不可以。抽象类的实例是它的子类给出的。接口的实例是实现接口的类给出的。
在抽象类中加入一个方法,那么它的子类就同时有了这个方法。而在接口中加入新的方法,那么实现它的类就要重新编写(这就是为什么说接口是一个类的规范了)。
接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。此外接口不能包含字段、构造函数、析构函数、静态成员或常量。
还有一点,我们在VS中实现接口时会发现有2个选项,一个是实现接口,一个是显示实现接口。实现接口就是我们平常理解的实现接口,而显示实现接口的话,实现的方法是属于接口的,而不是属于实现类的。
4)密封类sealed
密封类不能被继承,
密封方法可以重写基类中的方法,但其本身不能在任何派生类中进一步重写,当应用于方法或属性时,sealed修饰符必须始终于override一起使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PetShop
{
/// <summary>
/// 接口interface:指定一组成员函数,但本身不实现它们
/// </summary>
interface ICatchMice
{
/// <summary>
/// 默认public,但不能加public
/// </summary>
void CatchMice();
}
interface IClimbTree
{
void ClimbTree();
}
/// <summary>
/// 父类、基类,所有类都继承于Object,省略时默认继承于Object
/// </summary>
public class Pet
{
protected string name;
protected int age;
/// <summary>
/// 构造函数
/// </summary>
public Pet() { }
public Pet(string name) {
this.name = name;
this.age = 0;
}
/// <summary>
/// 成员函数
/// </summary>
public void PrintName()
{
Console.WriteLine("Pet`s name is " + this.name);
}
public void PrintAge()
{
Console.WriteLine(this.name + "`s age is " + this.age);
}
/// <summary>
/// 虚方法
/// </summary>
virtual public void Speak()
{
Console.WriteLine("Pet is speaking");
}
/// <summary>
/// 重载运算符
/// </summary>
/// <param name="pet">Pet对象</param>
/// <returns>将Pet对象的年龄加1后返回</returns>
public static Pet operator ++(Pet pet)
{
++pet.age;
return pet;
}
/// <summary>
/// 泛型方法:可以包含在泛型类中,也可以包含在普通类中
/// 约束规则:一个泛型类(类名或class或struct),多个接口(接口名),new()
/// </summary>
/// <param name="target">T类型的对象</param>
public void IsHappy<T>(T target) where T:Pet
{
Console.WriteLine(target.ToString()+ " is happy");
}
}
/// <summary>
/// 单继承:只能继承于一个父类
/// </summary>
public class Dog : Pet
{
/// <summary>
/// 静态成员字段
/// </summary>
static int num;
/// <summary>
/// 委托与事件发布者
/// </summary>
public delegate void Handler();
public static event Handler NewDog;
/// <summary>
/// 静态构造方法中不允许出现访问修饰符
/// </summary>
static Dog()
{
num = 0;
}
/// <summary>
/// this表示当前对象,base表示父类对象
/// </summary>
/// <param name="name">初始化名字</param>
public Dog(string name):base(name)
{
//this.name = name;
num++;
//触发事件
if (NewDog != null)
{
NewDog();
}
}
/// <summary>
/// 隐藏
/// </summary>
new public void PrintName()
{
Console.WriteLine("宠物狗的名字是" + this.name);
}
/// <summary>
/// 重写
/// </summary>
override public void Speak()
{
Console.WriteLine("Dog is speaking" + " wow");
}
/// <summary>
/// 静态方法只能访问静态成员,非静态方法可以访问静态也可以访问非静态成员
/// 静态方法只能通过类名调用,非静态方法只能通过对象访问
/// </summary>
public static void ShowNum()
{
Console.WriteLine("Dog's number is " + num);
}
/// <summary>
/// 自定义类的隐式转换
/// </summary>
/// <param name="dog">原始类对象</param>
/// <returns>目标类对象</returns>
public static implicit operator Cat(Dog dog)
{
return new Cat(dog.name);
}
/// <summary>
/// 被委托方法
/// </summary>
public void WagTail()
{
Console.WriteLine(this.name + " wag tail");
}
}
/// <summary>
/// 类是单继承,接口是多实现
/// </summary>
public class Cat : Pet,ICatchMice,IClimbTree
{
public Cat(string name):base(name)
{
//this.name = name;
}
/// <summary>
/// 隐藏
/// </summary>
new public void PrintName()
{
Console.WriteLine("宠物猫的名字是" + this.name);
}
/// <summary>
/// 重写
/// </summary>
override public void Speak()
{
Console.WriteLine("Cat is speaking" + " mom");
}
/// <summary>
/// 必须实现接口里的全部函数
/// </summary>
public void CatchMice()
{
Console.WriteLine("Catch Mice");
}
public void ClimbTree()
{
Console.WriteLine("Climb Tree");
}
/// <summary>
/// 自定义类的显式转换
/// </summary>
/// <param name="cat">原始类对象</param>
/// <returns>目标类对象</returns>
public static explicit operator Dog(Cat cat)
{
return new Dog(cat.name);
}
/// <summary>
/// 被委托方法
/// </summary>
public void InnocentLook()
{
Console.WriteLine(this.name + " innocent look");
}
}
/// <summary>
/// 实现泛型接口
/// </summary>
public class Labrador : Dog, ILearn<SitDogCmd>, ILearn<SpeakDogCmd>
{
public Labrador(string name) : base(name) { }
public void Act(SitDogCmd cmd)
{
Console.WriteLine(cmd.GetCmd());
}
public void Act(SpeakDogCmd cmd)
{
Console.WriteLine(cmd.GetCmd());
}
}
/// <summary>
/// 抽象类,抽象方法
/// </summary>
public abstract class DogCmd
{
public abstract string GetCmd();
}
/// <summary>
/// 实现抽象类,重写抽象方法
/// </summary>
public class SitDogCmd : DogCmd
{
public override string GetCmd()
{
return "Sit Down";
}
}
public class SpeakDogCmd : DogCmd
{
public override string GetCmd()
{
return "wow";
}
}
/// <summary>
/// 继承抽象类并实现抽象属性或抽象方法
/// </summary>
public class DogFood:Food
{
private double weight;
/// <summary>
/// 使用override重写抽象属性
/// </summary>
override public double Weight {
get { return weight; }
set { weight = value; }
}
/// <summary>
/// 使用override重写抽象方法
/// </summary>
public override void NiceFood()
{
Console.WriteLine("大黄牌狗粮");
}
}
/// <summary>
/// 静态类
/// </summary>
public static class PetGuide
{
/// <summary>
/// 静态方法与静态类之间没有必然关系(类似sealed)
/// </summary>
/// <param name="dog"></param>
public static void HowToFeed(this Dog dog)
{
Console.WriteLine("play a vedio about how to feed dog!");
}
}
/// <summary>
/// 泛型类:类的模板
/// </summary>
/// <typeparam name="T">具体类型</typeparam>
public class Cage<T> where T:Pet
{
T[] PetArr;
readonly int ArrSize;
int num;
public Cage(int n)
{
ArrSize = n;
num = 0;
PetArr = new T[ArrSize];
}
public void PutIn(T pet)
{
if (num < ArrSize)
{
PetArr[num++] = pet;
}
else
{
Console.WriteLine("Cage is full!");
}
}
public T TakeOut()
{
if (num > 0)
{
return PetArr[--num];
}
else
{
Console.WriteLine("Cage is empty!");
return default(T);
}
}
}
/// <summary>
/// 泛型接口:接口的模板
/// </summary>
/// <typeparam name="T"></typeparam>
interface ILearn<C> where C:DogCmd
{
void Act(C cmd);
}
/// <summary>
/// 事件的订阅者
/// </summary>
public class Client
{
public void WangADog()
{
Console.WriteLine("Great! I want to see the new dog");
}
}
class Program
{
/// <summary>
/// 委托方法
/// </summary>
delegate void ActCute();
static void Main(string[] args)
{
//继承,隐藏,虚方法,构造方法
{
Pet pet = new Pet("萌萌");
pet.PrintName();
pet.Speak();
Dog dog = new Dog("小白");
dog.PrintName();
dog.Speak();
Cat cat = new Cat("小花");
cat.PrintName();
cat.Speak();
}
// 使用基类类型的数组作为对象容器
{
Pet[] pets = new Pet[] { new Pet("萌萌"), new Dog("小白"), new Cat("小花") };
foreach (Pet p in pets)
{
p.PrintName();
p.Speak();
}
}
//抽象类与抽象方法
{
DogFood dogFood = new DogFood();
dogFood.Weight = 50;
dogFood.NiceFood();
}
//实现接口
{
Cat cat2 = new Cat("Tom");
ICatchMice icm = (ICatchMice)cat2;
IClimbTree ict = (IClimbTree)cat2;
cat2.CatchMice();//通过类调用实现了的接口函数
icm.CatchMice();//通过接口调用其中包含的函数
cat2.ClimbTree();
ict.ClimbTree();
}
//静态成员
{
Dog.ShowNum();
}
//静态类
{
Dog dog2 = new Dog("激萌的小黑");
dog2.HowToFeed();
}
//装箱与拆箱
{
int i = 5;
object o = i;//自动装箱:将值类型转换为引用类型
i = 10;
o = 20;
int j = (int)o;//手动拆箱:将装箱后的对象转换为值类型
Console.WriteLine("i = " + i + ",o = " + o + ",j = " + j);
}
//自定义类转换
{
Dog dog3 = new Dog("激萌的小黄");
dog3.PrintName(); dog3.Speak();
Cat cat3 = dog3;
cat3.PrintName(); cat3.Speak();
Dog dog4 = (Dog)cat3;
dog4.PrintName(); dog4.Speak();
}
// 重载运算符
Pet[] petss = new Pet[] { new Pet("萌萌"), new Dog("小白"), new Cat("小花") };
for (int i = 0; i < petss.Length; i++)//此处注意for与foreach的区别
{
petss[i].PrintAge();
petss[i]++;
petss[i].PrintAge();
}
//泛型类:功能类似一个类模板
{
var DogCage = new Cage<Dog>(1);
DogCage.PutIn(new Dog("A"));
DogCage.PutIn(new Dog("B"));
DogCage.TakeOut().PrintName();
//DogCage.TakeOut().PrintName();
var CatCage = new Cage<Cat>(1);
CatCage.PutIn(new Cat("C"));
CatCage.PutIn(new Cat("D"));
CatCage.TakeOut().PrintName();
//CatCage.TakeOut().PrintName();
}
//泛型方法:方法的模板
{
new Pet().IsHappy<Cat>(new Cat("B"));
//new Pet().IsHappy<int>(3);
}
//约束:缩小泛型参数的范围,可应用于泛型类和泛型方法
{
var DogCage = new Cage<Dog>(1);
DogCage.PutIn(new Dog("A"));
DogCage.TakeOut().PrintName();
//var icCage = new Cage<IClimbTree>(1);
new Pet().IsHappy<Cat>(new Cat("B"));
//new Pet().IsHappy<int>(3);
}
//泛型接口
{
Labrador dog = new Labrador("A");
dog.Act(new SitDogCmd());
dog.Act(new SpeakDogCmd());
}
//列表List,动态数组ArrayList,字典Dictionary,栈Stack,队列Queue
{
List<Pet> plist = new List<Pet>();
plist.Add(new Pet("萌萌"));
plist.Add(new Dog("小白"));
plist.Add(new Cat("小花"));
plist.RemoveAt(1);
foreach (Pet p in plist)
{
p.PrintName();
}
Dictionary<string, Dog> ddic = new Dictionary<string, Dog>();
ddic.Add("A", new Dog("A"));
ddic.Add("B", new Dog("B"));
ddic.Add("C", new Dog("C"));
ddic["A"].PrintName();
Stack<Pet> pstack = new Stack<Pet>();
pstack.Push(new Dog("AA"));
pstack.Push(new Cat("BB"));
pstack.Peek().PrintName();
pstack.Pop();
pstack.Peek().PrintName();
pstack.Pop();
Queue<Pet> pqueue = new Queue<Pet>();
pqueue.Enqueue(new Dog("AAA"));
pqueue.Enqueue(new Cat("BBB"));
pqueue.Dequeue().PrintName();
pqueue.Dequeue().PrintName();
}
//委托
{
ActCute actCute = new Dog("A").WagTail;
actCute += new Cat("B").InnocentLook;
actCute();
}
//Lambda表达式
{
ActCute actCute = new Dog("A").WagTail;
actCute += new Cat("B").InnocentLook;
actCute += () =>
{
Console.WriteLine("do nothing");
};
actCute();
}
//事件:发布者,订阅者,触发事件,注册事件
{
Client c1 = new Client();
Client c2 = new Client();
// 注册事件
Dog.NewDog += c1.WangADog;
Dog.NewDog += c1.WangADog;
new Dog("小Q");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PetShop
{
/// <summary>
/// 包含抽象方法的类是抽象类
/// </summary>
abstract public class Food
{
public double price;
/// <summary>
/// 抽象属性
/// </summary>
abstract public double Weight
{
get;
set;
}
/// <summary>
/// 抽象方法
/// </summary>
abstract public void NiceFood();
}
}
课程地址:
https://www.imooc.com/learn/422
https://www.imooc.com/learn/554
https://www.imooc.com/learn/806