1 背景动机

关于模块或者程序集初始化工作一直是C#的一个痛点,微软内部外部都有大量的报告反应很多客户一直被这个问题困扰,这还不算没有统计上的客户。那么解决这个问题,还有基于什么样的考虑呢?

  • 在库加载的时候,能以最小的开销、无需用户显式调用任何接口,使客户做一些期望的和一次性的初始化。

  • 当前静态构造函数方法的一个最大的问题是运行时会对带有静态构造函数的类型做一些额外的检查。这是因为要决定静态构造函数是否需要被运行所必须的一步,但是这个又有着显著的开销影响。

  • 使源代码生成器在不需要用户显式调用一些东西的情况下能运行一些全局的初始化逻辑。

2 详细设计

C# 9.0将模块初始化器设计为一个Attribute,用这个Attribute来修饰进行模块初始化逻辑的方法,就实现了模块初始化功能。这个Attribute被命名为ModuleInitializerAttribute,具体定义如下:

using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}

如果要使用模块初始化器,你只要将ModuleInitializerAttribute用在符合下面要求的方法上就可以了。

  1. 该方法必须使静态的、无参的、返回值为void的函数。

  2. 该方法不能是泛型或者包含在泛型类型里

  3. 该方法必须是可从其所在模块里访问的。也就是说,方法的有效访问符必须是internal或者public,不能是局部方法。

using System.Runtime.CompilerServices;
class MyClass
{
[ModuleInitializer]
internal static void Initializer()
{
// ...
}
}

被修饰为ModuleInitializerAttribute的静态方法会被编译器在编译时,在全局的静态构造函数中生成此代码调用。如果有多个被修饰为初始化器的函数,则每个函数生成一个初始化器代码调用,这些初始化器代码调用代码会按照一定的顺序(类型名称顺序和代码顺序)生成。当模块在被加载时,全局静态构造函数开始执行,从而完成模块代码初始化工作。

3 问题与最佳实践

模块初始化器与静态构造函数之间有着一定的关联影响。因为模块初始化器是一个静态方法,因而其被调用执行前,必然会引起其所处类型的静态构造函数的执行。请参考下列示例:

static class ModuleInit
{
static ModuleInit()
{
//先执行
Console.WriteLine("ModuleInit静态构造函数 cctor");
} [ModuleInitializer]
internal static void Initializer()
{
//在静态构造函数执行后才执行
Console.WriteLine("模块初始化器");
}
}

在一个模块中指定多个模块初始化器的时候,他们之间的顺序也是一个值得注意的问题。以上这些问题的存在,就要求我们注意以下几点:

  • 在指定了模块初始化器的类型中,不要在静态构造函数中,写与模块初始化器中代码有着顺序依赖代码,最好的就是不要使用静态构造函数。

  • 多个模块初始化器之间的代码,也不要有任何依赖关系,保持各个初始化器代码的独立性。

4 结束语]

日常开发中,我们通常需要在模块初始化的时候,做一些前置性的准备工作,以前常采用静态构造函数这种不具有全局性方法,局限性很大,现在,这些都得到了完美解决。

如对您有价值,请推荐,您的鼓励是我继续的动力,在此万分感谢。关注本人公众号“码客风云”,享第一时间阅读最新文章。

C# 9.0新特性详解系列之三:模块初始化器的更多相关文章

  1. C# 9.0新特性详解系列之五:记录(record)和with表达式

    1 背景与动机 传统面向对象编程的核心思想是一个对象有着唯一标识,表现为对象引用,封装着随时可变的属性状态,如果你改变了一个属性的状态,这个对象还是原来那个对象,就是对象引用没有因为状态的改变而改变, ...

  2. C#9.0新特性详解系列之六:增强的模式匹配

    自C#7.0以来,模式匹配就作为C#的一项重要的新特性在不断地演化,这个借鉴于其小弟F#的函数式编程的概念,使得C#的本领越来越多,C#9.0就对模式匹配这一功能做了进一步的增强. 为了更为深入和全面 ...

  3. C# 9.0新特性详解系列之一:只初始化设置器(init only setter)

    1.背景与动机 自C#1.0版本以来,我们要定义一个不可变数据类型的基本做法就是:先声明字段为readonly,再声明只包含get访问器的属性.例子如下: struct Point { public ...

  4. C# 9.0新特性详解系列之二:扩展方法GetEnumerator支持foreach循环

    1.介绍 我们知道,我们要使一个类型支持foreach循环,就需要这个类型满足下面条件之一: 该类型实例如果实现了下列接口中的其中之一: System.Collections.IEnumerable ...

  5. [转]Servlet 3.0 新特性详解

    原文地址:http://blog.csdn.net/xiazdong/article/details/7208316 Servlet 3.0 新特性概览 1.Servlet.Filter.Listen ...

  6. Servlet 3.0 新特性详解

    转自:http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/#major3 Servlet 是 Java EE 规范体系的重要组成部分,也是 ...

  7. 【转帖】Servlet 3.0 新特性详解

    http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ Servlet 3.0 新特性概述 Servlet 3.0 作为 Java EE 6 ...

  8. Servlet 3.0 新特性详解 (转载)

    原文地址:https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ Servlet 3.0 新特性概述 Servlet 3.0 作为 Jav ...

  9. Android6.0 新特性详解

    一 运行时权限 Android6.0 引入了一个新的应用权限模型,期望对用户更容易理解,更易用和更安全.该模型将标记为危险的权限从安装时权限(Install Time Permission)模型 移动 ...

随机推荐

  1. Linux防火墙篇

    关闭firewall:systemctl stop firewalld.service    #停止firewallsystemctl disable firewalld.service   #禁止f ...

  2. [Luogu P1450] [HAOI2008]硬币购物 背包DP+容斥

    题面 传送门:https://www.luogu.org/problemnew/show/P1450 Solution 这是一道很有意思的在背包里面做容斥的题目. 首先,我们可以很轻松地想到暴力做背包 ...

  3. FloodFill算法详解及应用

    啥是 FloodFill 算法呢,最直接的一个应用就是「颜色填充」,就是 Windows 绘画本中那个小油漆桶的标志,可以把一块被圈起来的区域全部染色. 这种算法思想还在许多其他地方有应用.比如说扫雷 ...

  4. 公钥、私钥、SSL/TLS、会话密钥、DES【转载】

    原文链接:https://www.cnblogs.com/thbCode/p/5829719.html 一,公钥私钥1,公钥和私钥成对出现2,公开的密钥叫公钥,只有自己知道的叫私钥3,用公钥加密的数据 ...

  5. 【Luogu】P2292 [HNOI2004]L语言 题解

    前置芝士:\(Trie\)字典树 这道题,说是AC自动机,实际上一个\(Trie+\)队列轻松搞定. 首先,我们对所有单词建一棵\(Trie\). 然后,定义一个空队列\(Q\),初始时把\(-1\) ...

  6. C# Base64解码小工具编写

    1 界面如下 2 关键代码如下 try { var callback = reqStr.Deserialize<dynamic>(); resStr = Newtonsoft.Json.J ...

  7. 阿里P8大佬熬夜10天,把所有Android第三方库整理成了PDF

    缘起 随着互联网企业的不断发展,产品项目中的模块越来越多,用户体验要求也越来越高,想实现小步快跑.快速迭代的目的越来越难,还有应用之间的互相调用等等问题,插件化技术应用而生.如果没有插件化技术,美团. ...

  8. 对于button元素的理解

    button有四种常用的类型: submit:  此按钮将表单数据提交给服务器.如果未指定属性,或者属性动态更改为空值或无效值,则此值为默认值. reset:  此按钮重置所有组件为初始值. butt ...

  9. 【Kata Daily 190903】String incrementer(字符串增量器)

    原题: Your job is to write a function which increments a string, to create a new string. If the string ...

  10. WSL Ubuntu 18.04 LTS + VS Code

    WSL Ubuntu 18.04 LTS + VS Code ​ WSL(Windows Subsystem for Linux)使得Windows用户能够在Windows系统上使用原生的Linux环 ...