原网页
复习方法:当解释定义题做一遍就行了(先在word里敲上概念,然后解释概念)
不要太纠结,过一遍
每日必复习,直到熟练
善用面向搜索引擎编程,多去知乎以及其他博客搜集资料提升理解,只要有不会的就去搜索
成员变量
变量是类的属性或数据成员,用于存储数据
成员函数
函数是一系列执行指定任务的语句。类的成员函数是在类内声明的。
成员,指类的成员
实例化
实例化是指在面向对象的编程中,用类创建对象的过程称为实例化。
实例就是对象。
可否理解,类是抽象的,看不见摸不着的,只能形容的东西,(比如猫有腿,眼睛,嘴巴等,形容越多越具体)
对象是实际的,能摆在眼前的,(比如真的见到了一只猫,或者说,我们发动上帝之手,按照类的形容创造了世界上第一只猫,,说的再多,最后也只有实际做出来才有意义)
标识符
标识符是用来识别类、变量、函数或任何其它用户定义的项目。
标识符必须以字母、下划线或 @ 开头,后面可以跟一系列的字母、数字( 0 - 9 )、下划线( _ )、@。
标识符中的第一个字符不能是数字。
标识符必须不包含任何嵌入的空格或符号,比如 ? - +! # % ^ & * ( ) [ ] { } . ; : " ’ / \。
标识符不能是 C# 关键字。除非它们有一个 @ 前缀。 例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字。
标识符必须区分大小写。大写字母和小写字母被认为是不同的字母。
不能与C#的类库名称相同。
就是你的类名,变量名,函数名
C# 关键字
关键字是 C# 编译器预定义的保留字。这些关键字不能用作标识符,在 C# 中,有些关键字在代码的上下文中有特殊的意义,如 get 和 set,这些被称为上下文关键字(contextual keywords)。
C# 数据类型
值类型(Value types)
引用类型(Reference types)
指针类型(Pointer types)
值类型
值类型直接包含数据。
如需得到一个类型或一个变量在特定平台上的准确尺寸,可以使用 sizeof 方法。
Console.WriteLine(“Size of int: {0}”, sizeof(int));
Console.ReadLine();
引用类型
引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
ps:(但是引用并不是地址,只是指向地址,引用时内存的别名。指针指向一块内存,内容是所指内存的地址)
换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。内置的 引用类型有:object、dynamic 和 string。
对象(Object)类型
对象(Object)类型 是 C# 通用类型系统(Common Type System - CTS)中所有数据类型的终极基类。Object 是 System.Object 类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。但是,在分配值之前,需要先进行类型转换。
当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。
object obj;
obj = 100; // 这是装箱
动态(Dynamic)类型
这是什么?
您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。
态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的,而动态类型变量的类型检查是在运行时发生的。
字符串(String)类型
字符串(String)类型 允许您给变量分配任何字符串值。字符串(String)类型是 System.String 类的别名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号和 @引号。
string 字符串的前面可以加 @(称作"逐字字符串")将转义字符(\)当作普通字符对待
@ 字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内。
定义引用类型有:class、interface 或 delegate。
指针类型(Pointer types)
指针类型变量存储另一种类型的内存地址。
C# 类型转换
隐式类型转换 - 这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。例如,从小的整数类型转换为大的整数类型,从派生类转换为基类。
显式类型转换 - 显式类型转换,即强制类型转换。显式转换需要强制转换运算符,而且强制转换会造成数据丢失
C# 变量
一个变量只不过是一个供程序操作的存储区的名字。在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。
C# 中的变量定义 int i, j, k; (定义就是声明
C# 中的变量初始化 a = 10; 变量可以在声明时被初始化(指定一个初始值
C# 常量
常量是固定值,程序执行期间不会改变。
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。
整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,
定义常量
常量是使用 const 关键字来定义的 。
C# 运算符
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。
C# 判断 没啥好说的
C# 循环
break 语句终止 loop 或 switch 语句,程序流将继续执行紧接着 loop 或 switch 的下一条语句。
continue 语句引起循环跳过主体的剩余部分,立即重新开始测试条件。
C# 封装
封装 被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中"。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。C# 封装根据具体的需要,设置使用者的访问权限,并通过 访问修饰符 来实现。一个 访问修饰符 定义了一个类成员的范围和可见性。C# 支持的访问修饰符如下所示:
public:所有对象都可以访问;
private:对象本身在对象内部可以访问;
protected:只有该类对象及其子类对象可以访问
internal:同一个程序集的对象可以访问;
protected internal:访问限于当前程序集或派生自包含类的类型。
C# 方法
一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块。
在 C# 中,有三种向方法传递参数的方式:值参数,引用参数,输出参数
C# 可空类型(Nullable)
C# 提供了一个特殊的数据类型,nullable 类型(可空类型),可空类型可以表示其基础值类型正常范围内的值,再加上一个 null 值。
< data_type> ?
C# 数组(Array)
数组是一个存储相同类型元素的固定大小的顺序集合。
数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例。
类是引用类型的数据类型,所以说new不是专门用来给类创建实例的,而是用来给引用类型创建实例的。
比如这里,创建的是数组的实例。
C# 字符串(String)
C# 结构体(Struct)
在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。
类 vs 结构
类和结构有以下几个基本的不同点:
类是引用类型,结构是值类型。
结构不支持继承。
结构不能声明默认的构造函数。
C# 枚举(Enum)
枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。
C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。
C# 类(Class)
当你定义一个类时,你定义了一个数据类型的蓝图。这实际上并没有定义任何的数据,但它定义了类的名称意味着什么,也就是说,类的对象由什么组成及在这个对象上可执行什么操作。对象是类的实例。构成类的方法和变量称为类的成员。
C# 中的构造函数
类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。
构造函数的名称与类的名称完全相同,它没有任何返回类型。
C# 中的析构函数
类的 析构函数 是类的一个特殊的成员函数,当类的对象超出范围时执行。
析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。
析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
C# 类的静态成员
我们可以使用 static 关键字把类成员定义为静态的。当我们声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个该静态成员的副本。
关键字 static 意味着类中只有一个该成员的实例。静态变量用于定义常量,因为它们的值可以通过直接调用类而不需要创建类的实例来获取。
C# 继承
继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类,
已有的类被称为的基类,这个新的类被称为派生类。
C# 不支持多重继承。但是,您可以使用接口来实现多重继承
C# 接口(Interface)
接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。
接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。
也许:接口就是告诉你,继承了我之后你要实现哪些功能,但是我不告诉你该怎么办,然后派生类来说明这个功能要怎么实现,也就是说,不同派生类可以用不同方法实现同一接口的功能?也就是下面的多态性?
interface IMyInterface
{
// 接口成员
void MethodToImplement();
}
class InterfaceImplementer : IMyInterface//接口的实现与类的继承语法格式类似
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
}
public void MethodToImplement()//这里就是所谓成员的定义是派生类的责任
{
Console.WriteLine(“MethodToImplement() called.”);
}
}
如果一个接口继承多个接口,那么实现类或结构就需要实现所有接口的成员。
C# 多态性
多态是同一个行为具有多个不同表现形式或形态的能力。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。
在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自 Object
override叫重写
静态多态性
在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:
函数重载
您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。
C# 运算符重载
您可以重定义或重载 C# 中内置的运算符。因此,程序员也可以使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。
public static Box operator+ (Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
这样子任意两个Box类对象都可以相加了
+, -, !, ~, ++, – 这些一元运算符只有一个操作数,且可以被重载。
+, -, *, /, % 这些二元运算符带有两个操作数,且可以被重载。
==, !=, <, >, <=, >= 这些比较运算符可以被重载。
&&, || 这些条件逻辑运算符不能被直接重载。
+=, -=, *=, /=, %= 这些赋值运算符不能被重载。
=, ., ?:, ->, new, is, sizeof, typeof 这些运算符不能被重载。
动态多态性
C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。
您不能创建一个抽象类的实例。
您不能在一个抽象类外部声明一个抽象方法。
通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。
虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。
动态多态性是通过 抽象类 和 虚方法 实现的。
关于抽象类和接口
资料来源
一、抽象类:
抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们。
二、接口:
接口是引用类型的,类似于类,和抽象类的相似之处有三点:
1. 不能实例化;
2. 包含未实现的方法声明;
3. 派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);
另外,接口有如下特性:
接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。
三、抽象类和接口的区别:
1. 类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类叫做抽象类.而接口只是一个行为的规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做。。。”。抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中;
2. 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;
3. 一个类一次可以实现若干个接口,但是只能扩展一个父类;
4. 接口可以用于支持回调,而继承并不具备这个特点;
5. 抽象类不能被密封;
6. 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的;
7.(接口)与非抽象类类似,抽象类也必须为在该类的基类列表中列出的接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上;
8. 抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现;
9. 好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染;
10. 尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们全部加载到栈中!后果可想而知。(结合堆栈原理理解)。同时,有心的朋友可以留意到微软在构建一个类时,很多时候用到了对象组合的方法。比如 asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是非常基本的一个设计原则;
11.如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。
四、抽象类和接口的使用:
1. 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本;
2.如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口;
3.如果要设计大的功能单元,则使用抽象类。如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类;
4.抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。
以下是我在网上看到的几个形象比喻。
1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类;
2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承),一个门可以有锁(接口)也可以有门铃(多实现)。门(抽象类)定义了你是什么,接口(锁)规定了你能做什么(一个接口最好只能做一件事,你不能要求锁也能发出声音吧(接口污染))。
ps:也就是说,在具体的程度上,对象>类>抽象类,平时之前举的例子都是很大的,都可以说是抽象类? 狗—哈士奇—A家的哈士奇
C# 异常处理
异常提供了一种把程序控制权从某个部分转移到另一个部分的方式。C# 异常处理时建立在四个关键词之上的:try、catch、finally 和 throw。
try:一个 try 块标识了一个将被激活的特定的异常的代码块。后跟一个或多个 catch 块。
catch:程序通过异常处理程序捕获异常。catch 关键字表示异常的捕获。
finally:finally 块用于执行给定的语句,不管异常是否被抛出都会执行。例如,如果您打开一个文件,不管是否出现异常文件都要被关闭。
throw:当问题出现时,程序抛出一个异常。使用 throw 关键字来完成。
C# 命名空间(Namespace)
在一个命名空间中声明的类的名称与另一个命名空间中声明的相同的类的名称不冲突
using 关键字
using 关键字表明程序使用的是给定命名空间中的名称。例如,我们在程序中使用 System 命名空间,其中定义了类 Console。
命名空间可以被嵌套,即您可以在一个命名空间内定义另一个命名空间,
C# 预处理器指令
预处理器指令指导编译器在实际编译开始之前对信息进行预处理。
所有的预处理器指令都是以 # 开始。预处理器指令不是语句,所以它们不以分号(;)结束。如#define
C# 正则表达式
看不懂
#文件的输入与输出
一个 文件 是一个存储在磁盘中带有指定名称和目录路径的数据集合。当打开文件进行读写时,它变成一个 流。
从根本上说,流是通过通信路径传递的字节序列。有两个主要的流:输入流 和 输出流。输入流用于从文件读取数据(读操作),输出流用于向文件写入数据(写操作)。//
C# 特性(Attribute)
特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性。
虽然有点懵,但是还是努力理解了一下
第一个问题,函数参数是object,是指参数数据类型是object(对象类型?)看到加点东西就简单我也是傻了,加什么啊
看到Func还一下子没反应过来,Func就是方法啊,根据字面意思getFuncData(得到方法数据)返回值是类型叫FuncData的数组。
而FuncData准确来说是一个结构体类型,而在这个叫FuncData的结构体里存着一个函数的信息,
给每个类都手写一个FuncData的表,FuncData本身是一个结构,应该是写在类外面的没错,写一个表应该是指在每一个类中将每个方法存到表里
那么回到最初的需求,这个函数可以调用父类里的getFuncData方法获取所有方法数据了,即使不知道也不告诉有什么方法
但是还是不明白这个函数参数是干嘛用的。。
那么也就是说,这个Attribute特性,指的是给类增加某些特性,
完全陌生,例子举得好少,不知道到底是干嘛用,怎么用的。
就不全部复制一