C#常识篇(二)

委托和事件的区别

委托可以认为是对指定签名的函数的引用,通过委托可以实现将函数作为参数传递或者间接调用函数,委托是类型安全的,仅指向与其声明时指定签名相匹配的函数。委托可以分为单播委托和多播委托,二者的区别在于是对单个方法还是一组方法的引用,多播委托则可以通过特定的符号"+="和"-="来完成函数的订阅和取消订阅。

事件则是一种特殊的多播委托,其相比于普通的多播委托更加安全,事件将多播委托的调用权限隔离在其所在类的内部,并对外部关闭了直接通过赋值符号"="修改多播委托实例的入口,使得外部调用者仅能够进行基本的函数订阅和取消订阅的操作。

多播委托的底层实现

多播委托实际上是一个类实例,其中定义了一个函数引用列表用于存储订阅的函数。当调用多播委托时,将由CLR来遍历该函数引用列表,并按照订阅顺序依次调用函数。

重载和重写的区别

重载是一种编译时多态,重载函数的名称相同但参数列表不同,在调用时编译器会自动根据传递的参数列表适配指定形式的重载函数。

重写是一种运行时多态,子类重写父类的方法,在调用时根据实例对象的类型而适配重写函数。

for和foreach的区别

以数组为例,for循环根据数组下标遍历元素,而foreach循环通过生成数组的临时迭代器来遍历元素,并且foreach循环是只读的,修改操作可能导致迭代器失效,例如一边遍历一边删除元素的行为。所以通常来说优先考虑使用for循环。

类和结构体的区别

1.类的实例对象保存在堆上,而其引用保存在栈上;结构体的数据和存储其的变量均保存在栈上。

2.类能够实现继承、多态和封装,能够实现接口;结构体仅能实现接口。

3.类为引用类型,可以有多个变量指向同一个类的实例,其中一个变量对实例的修改就会影响其它变量;结构体为值类型,多个变量指向结构体的实例,实际上是各自存储了结构体的副本,所以各自的修改互不影响。

4.类更适合大型对象、需要封装较多行为或者需要实现继承和多态的情况;结构体则适用于轻量的或具有少量行为的或不可变的数据结构,结构体更偏向于数据而不是行为,这与类有所不同。

foreach的原理

foreach是一种结合迭代器模式遍历实现了IEnumerable(或IEnumerable<T>)接口的容器类的语句,这两个接口会提供获取IEnumerator(或IEnumerator<T>)类型迭代器的方法,foreach会在运行时自动获取迭代器并启动对容器类的遍历。

协变和逆变

协变则是将派生程度更大的赋值给派生程度更小的变量,逆变则是将派生程度更小的赋值给派生程度更大的变量。协变和逆变通常针对数组、委托和泛型参数,例如通过out或in关键字修饰泛型参数,使得方法组具有协变或逆变性,协变性通常体现在方法的返回类型,而逆变性通常体现在方法的参数类型。

结构体

结构体隐式继承自System.ValueType,属于值类型,所以其数据和引用它的变量均存储在栈上。以下是结构体的一些特性:

1.无法实现多态和继承,但是可以实现接口,可以重写Equals、ToString、GetHashCode三个方法;

2.无法声明本结构体类型的字段或属性;

3.如果不存在属性且未自定义构造函数,可以不通过new关键字创建结构体实例,但是在使用该结构体实例前须对所有字段进行初始化;

4.自定义的构造函数将覆盖默认的无参构造函数,所以须通过new关键字创建结构体实例,自定义的构造函数须对所有字段进行初始化;

结构体偏向于数据而不是行为,通过变量将结构体实例赋值给其它变量时会涉及到结构体的拷贝,对结构体的拷贝会涉及更多的性能开销。结构体的进阶使用可以参考readonly和init关键字相关知识。

常见修饰符

(1)public:能够在其声明所在的类或结构体甚至程序集外部访问,程序集外部访问需要引用其所在程序集;

(2)protected:能够在直接或间接派生类或其声明所在的类中访问;

(3)private:仅能够在其声明所在的类或结构体中访问;

(4)internal:能够在其声明所在的类或结构体之外但在所处程序集之内访问;

值得注意的是,未明确指定访问修饰符的类或结构体或接口默认为internal,未明确指定访问修饰符的类成员或结构体成员默认为private,接口成员默认为public。

静态构造函数

静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。 将在创建第一个实例或引用任何静态成员之前自动调用静态构造函数。 静态构造函数最多调用一次。如果静态字段的初始化并不复杂或者不涉及一些特殊的处理,那么建议在静态字段声明时即进行初始化,使用静态构造函数会影响运行时优化。常见的应用场景包括日志记录、创建非托管代码的包装类以及运行时的参数类型检查。

如果这篇文章对你有帮助,请给作者点个赞吧!

相关推荐
Dola_Pan6 分钟前
C语言:数组转换指针的时机
c语言·开发语言·算法
ExiFengs6 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj1234567898 分钟前
JDK1.8新增特性
java·开发语言
IT古董15 分钟前
【人工智能】Python在机器学习与人工智能中的应用
开发语言·人工智能·python·机器学习
繁依Fanyi19 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
湫ccc38 分钟前
《Python基础》之pip换国内镜像源
开发语言·python·pip
fhvyxyci39 分钟前
【C++之STL】摸清 string 的模拟实现(下)
开发语言·c++·string
qq_4597300342 分钟前
C 语言面向对象
c语言·开发语言
菜鸟学Python1 小时前
Python 数据分析核心库大全!
开发语言·python·数据挖掘·数据分析
一个小坑货1 小时前
Cargo Rust 的包管理器
开发语言·后端·rust