服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#条件编译、内联函数、CLS介绍

C#条件编译、内联函数、CLS介绍

2023-02-24 15:18痴者工良 C#

这篇文章介绍了C#的条件编译、内联函数、CLS,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

1、条件编译

#if 条件编译会隐藏非条件(#else if)代码,我们开发中很可能会忽略掉这部分代码,当我们切换条件常量到这部分代码时,很可能因为各种原因导致报错。

如果使用特性进行条件编译标记,在开发过程中就可以留意到这部分代码。

?
1
[Conditional("DEBUG")]

例如,当使用修改所有引用-修改一个类成员变量或者静态变量名称时,#if 非条件中的代码不会被修改,因为这部分代码“无效”,而且使用 [Conditional("DEBUG")] 的代码则跟条件无关,会被同步修改。

Conditional 特性标记的方法等,在开发过程中保持有效,当在编译时可能被排除。

代码片段只能使用 #if 了,如果是单个方法,则可以使用 Conditional 。

2、MethodImpl 特性

此特性在 System.Runtime.CompilerServices 命名空间中,指定如何实现方法的详细信息。

MethodImpl 特性可以影响 JIT 编译器的行为。

无法使用 MemberInfo.GetCustomAttributes 来获取此特性的信息,即不能通过获取特性的方法获取跟 MethodImpl 有关的信息(反射),只能调用 MethodInfo.GetMethodImplementationFlags() 或 ConstructorInfo.GetMethodImplementationFlags () 来检索。

MethodImpl 可以在方法以及构造函数上使用。

MethodImplOptions 用于设置编译行为,枚举值可组合使用,其枚举说明如下:

枚举 枚举值 说明
AggressiveInlining 256 如可能应将该方法进行内联。
AggressiveOptimization 512 此方法包含一个热路径,且应进行优化。
ForwardRef 16 已声明该方法,但在其他位置提供实现。
InternalCall 4096 该调用为内部调用,也就是说它调用了在公共语言运行时中实现的方法。
NoInlining 8 该方法不能为内联方法。 内联是一种优化方式,通过该方式将方法调用替换为方法体。
NoOptimization 64 调试可能的代码生成问题时,该方法不由实时 (JIT) 编译器或本机代码生成优化(请参阅 Ngen.exe)。
PreserveSig 128 完全按照声明导出方法签名。
Synchronized 32 该方法一次性只能在一个线程上执行。 静态方法在类型上锁定,而实例方法在实例上锁定。 只有一个线程可在任意实例函数中执行,且只有一个线程可在任意类的静态函数中执行。
Unmanaged 4 此方法在非托管的代码中实现。

Synchronized 修饰的方法可以避免多线程中的一些问题,但是不建议对公共类型使用锁定实例或类型上的锁定,因为 Synchronized 可以对非自己的代码的公共类型和实例进行锁定。 这可能会导致死锁或其他同步问题。

意思是说,如果共享的成员已经设置了锁,那么不应该再在 Synchronized 方法中使用,这样双重锁定容易导致死锁以及其他问题。

3、CLSCompliantAttribute

指示程序元素是否符合公共语言规范 (CLS)。

CLS规范可参考:

https://docs.microsoft.com/en-us/dotnet/standard/language-independence

全局开启方法:

程序目录下添加一个 AssemblyAttribytes.cs 文件,或者打开 obj 目录,找到 AssemblyAttributes.cs 结尾的文件,如 .NETCoreApp,Version=v3.1.AssemblyAttributes.cs,添加:

?
1
2
using System;   // 这行已经有的话不要加
[assembly: CLSCompliant(true)]

之后就可以在代码中使用 [CLSCompliant(true)] 特性。

局部开启:

也可以放在类等成员上使用:

?
1
[assembly: CLSCompliant(true)]

您可以将特性应用于 CLSCompliantAttribute 下列程序元素:程序集、模块、类、结构、枚举、构造函数、方法、属性、字段、事件、接口、委托、参数和返回值。 但是,CLS 遵从性的概念仅适用于程序集、模块、类型和类型的成员。

程序编译时默认不会检查代码是否符合 CLS 要求,但是如果你的可以是公开的(代码共享、Nuget 发布等),则建议使用使用 [assembly: CLSCompliant(true)] ,指明你的库符合 CLS 要求。

在团队开发中以及内部共享代码时,高质量的代码尤为重要,所以有必要使用工具检查代码,如 roslyn 静态分析、sonar 扫描等,也可以使用上面的特性,自动使用 CLS 检查。

CLS 部分要求:

  • 无符号类型不应成为该类的公共接口的一部分(私有成员可以使用),例如 UInt32 这些属于 C# 的类型,但不是 CLS “标准” 中的。

  • 指针等不安全类型不能与公共成员一起使用,就是公有方法中都不应该使用 unsafe 代码。(私有成员可以使用)。

  • 类名和成员名不应重名。虽然 C# 中区分大小写,但是 CLS 不建议同名非重载函数,例如 MYTEST 跟 Mytest。

  • 只能重载属性和方法,不应重载运算符。重载运算符容易导致调用者不知情时出现程序错误,并且重载运算符要排查问题十分困难。

我们可以编译以下代码,尝试使用 CLSCompliant :

?
1
2
3
4
5
6
7
8
9
10
11
[assembly: CLSCompliant(true)]
[CLSCompliant(true)]
public class Test
{
    public void MyMethod()
    {
    }
    public void MYMETHOD()
    {
    }
}

IDE 中会警告:warning CS3005: 仅大小写不同的标识符“Test.MYMETHOD()”不符合 CLS,编译时也会提示 Warn。当然,不会阻止编译,也不会影响程序运行。

总之,如果要标记一个程序集 CLS 规范,可以使用 [assembly: CLSCompliant(true)] 特性。

[CLSCompliant(true)] 特性指示这个元素符合 CLS 规范,这时编译器或者 IDE 会检查你的代码,检查是否真的符合规范。

如果偏偏要写不符合规范的代码,则可以使用 [CLSCompliant(false)]

4、必要时自定义类型别名

C# 也可以定义类型别名。

?
1
2
3
4
5
using intbyte = System.Int32;
using intkb = System.Int32;
using intmb = System.Int32;
using intgb = System.Int32;
using inttb = System.Int32;
?
1
2
byte[] fileByte = File.ReadAllBytes("./666.txt");
intmb size = fileByte.Length / 1024;

一些情况下,使用别名可以提高代码可读性。真实项目不要使用以上代码,我只是写个示例,这并不是合适的应用场景。

到此这篇关于C#条件编译、内联函数、CLS的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/whuanle/p/14141213.html

延伸 · 阅读

精彩推荐