c# 9.0新特性——模块初始化器

作者:MarkKang
出处:https://www.cnblogs.com/markkang/

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用在符合下面要求的方法上就可以了。

该方法必须使静态的、无参的、返回值为void的函数。
该方法不能是泛型或者包含在泛型类型里
该方法必须是可从其所在模块里访问的。也就是说,方法的有效访问符必须是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#教程前置性的准备工作,以前常采用静态构造函数这种不具有全局性方法,局限性很大,现在,这些都得到了完美解决。

以上就是c# 9.0新特性——模块初始化器的详细内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 要将C# 9.0升级到C# 10.0,你需要在Visual C#解决方案工程项目文件中进行配置。在"<PropertyGroup>" XML节点中添加"<LangVersion>10.0</LangVersion>",保存并重加载项目解决方案。这样就可以使用C# 10.0的特性了。\[1\]在C# 10.0中,你可以使用模式匹配来对Null类型进行判断,这在处理用户信息时非常有用。例如,你可以使用if(user is not null)来判断用户是否为空,并返回相应的结果。\[2\]此外,在C# 10.0中,你还可以使用顶级语句来简化代码的编写。\[2\]如果你想了解更多关于C# 10.0的改进,你可以查看MSIL中间语言的代码,其中包含了C# 10.0的一些特性的示例。\[3\]希望这些信息对你有帮助! #### 引用[.reference_title] - *1* *3* [C# 9.0语法标准 “函数指针” 深度解读!](https://blog.csdn.net/liulilittle/article/details/126670649)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C#: 8.0 和 9.0 常用特性](https://blog.csdn.net/sD7O95O/article/details/115910997)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值