条件属性如何工作?

2024-01-10

我有一些标记为的辅助方法[Conditional("XXX")]。目的是在仅存在 XXX 条件编译符号时使方法进行条件编译。我们使用它来调试和跟踪功能,并且效果很好。

在我研究条件编译如何工作的过程中,我发现了几个资料来源,说明了标记有Conditional属性将被放置在 IL 中,但对方法的调用将不会被执行。

代码如何编译成 IL 但不执行?我如何验证行为是否确实如描述的那样?我对 IL 没有做过太多的工作,所以我在这方面的技能有点薄弱。


这是由编译器控制的。所有方法都带有[Conditional]仍将包含在 MSIL 中,但将包含.custom instance详细说明的行[Conditional]。在方法调用者的编译时,编译器进行词法分析,然后进行语义分析和重载解析,并找到.custom instanceIL 在您放置的方法中[Conditional]在。因此它不会编译该调用。

所以:编译器编译了目标方法,但是不编译任何调用到那个方法。注意:该方法仍然存在,您仍然可以通过反射调用它。看the spec https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/attributes#conditional-methods

对条件方法的调用可以包含也可以省略,具体取决于调用时是否定义了该符号。如果定义了符号,则包含调用;否则,调用(包括接收者的评估和调用的参数)被省略。

你如何验证它?启动开发者命令提示符,输入ildasm <enter>并打开相关的dll/exe。查看主叫方和被叫方[Conditional]方法。你会看到被调用的方法有额外的 IL.custom instance,并且在您期望的地方省略了调用方行。使用下面的代码在控制台应用程序上尝试一下。

为什么?在某些情况下,它使条件调用比使用更简单#if. See Eric Lippert:条件编译和条件属性有什么区别? http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/

class Program
{
    static void Main(string[] args)
    {
        AlwaysEmit();
        DebugEmit();
        VerboseEmit();
    }

    public static void AlwaysEmit()
    {
        Console.WriteLine("Beam me up");
    }

    [Conditional("DEBUG")]
    public static void DebugEmit()
    {
        Console.WriteLine("Kirk out");
    }

    [Conditional("VERBOSE")]
    public static void VerboseEmit()
    {
        Console.WriteLine("Say that again?");
    }
}

而在相应的MSIL中,VerboseEmit包含在内,但未调用自Main:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       14 (0xe)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  call       void RateScope.SdrApi.UploaderConsoleApp.Program::AlwaysEmit()
  IL_0006:  nop
  IL_0007:  call       void RateScope.SdrApi.UploaderConsoleApp.Program::DebugEmit()
  IL_000c:  nop
  IL_000d:  ret
} // end of method Program::Main

...

.method public hidebysig static void  VerboseEmit() cil managed
{
  .custom instance void [mscorlib]System.Diagnostics.ConditionalAttribute::.ctor(string)
     = ( 01 00 07 56 45 52 42 4F 53 45 00 00 ) // ...VERBOSE..
  // Code size       13 (0xd)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "Say that again\?"
  IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000b:  nop
  IL_000c:  ret
} // end of method Program::VerboseEmit

奖励积分。查看控制台输出和 MSIL(相应地修改 Emit 方法):

static void Main(string[] args)
{
    int callCount = 0;
    AlwaysEmit(++callCount);
    VerboseEmit(++callCount);
    DebugEmit(++callCount);
    Console.WriteLine("Call count = " + callCount);
    Console.ReadLine();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

条件属性如何工作? 的相关文章

  • 从 MVC 迁移到 ASP.NET Core 3.1 中的端点路由时,具有角色的 AuthorizeAttribute 不起作用

    我正在尝试将我的项目从 UseMVC asp net core 2 2 兼容样式 升级到 UseEndpoint Routing 并且我的所有请求都被重定向到我的验证失败页面 它与声明有关 如果我删除 Authorize Roles Adm
  • 如何使用recv()检测客户端是否仍然连接(并且没有挂起)?

    我写了一个多客户端服务器程序C on SuSE Linux 企业服务器 12 3 x86 64 我为每个客户端使用一个线程来接收数据 我的问题是 我使用一个终端来运行服务器 并使用其他几个终端来运行服务器telnet到我的服务器 作为客户端
  • C++ 异步线程同时运行

    我是 C 11 中线程的新手 我有两个线程 我想让它们同时启动 我可以想到两种方法 如下 然而 似乎它们都没有按照我的预期工作 他们在启动另一个线程之前启动一个线程 任何提示将不胜感激 另一个问题是我正在研究线程队列 所以我会有两个消费者和
  • 检查算术运算中的溢出情况[重复]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • ASP MVC:服务应该返回 IQueryable 的吗?

    你怎么认为 你的 DAO 应该返回一个 IQueryable 以便在你的控制器中使用它吗 不 您的控制器根本不应该处理任何复杂的逻辑 保持苗条身材 模型 而不是 DAO 应该将控制器返回给视图所需的所有内容 我认为在控制器类中看到查询 甚至
  • 在 2D 中将一个点旋转另一个点

    我想知道当一个点相对于另一个点旋转一定角度时如何计算出新的坐标 我有一个块箭头 想要将其相对于箭头底部中间的点旋转角度 theta 这是允许我在两个屏幕控件之间绘制多边形所必需的 我无法使用和旋转图像 从我到目前为止所考虑的情况来看 使问题
  • Qt 创建布局并动态添加小部件到布局

    我正在尝试在 MainWindow 类中动态创建布局 我有四个框架 它们是用网格布局对象放置的 每个框架都包含一个自定义的 ClockWidget 我希望 ClockWidget 对象在调整主窗口大小时相应地调整大小 因此我需要将它们添加到
  • 基于xsd模式生成xml(使用.NET)

    我想根据我的 xsd 架构 cap xsd 生成 xml 文件 我找到了这篇文章并按照说明进行操作 使用 XSD 文件生成 XML 文件 https stackoverflow com questions 6530424 generatin
  • 无法将类型“System.IO.Stream”隐式转换为“Java.IO.InputStream”

    我提到了一些类似的问题 但没有一个涉及IO 当我使用时 我在java中使用了相同的代码Eclipse 那次就成功了 但现在我尝试在中使用这段代码Mono for Android C 它不起作用 我正在尝试运行此代码来创建一个InputStr
  • 将构建日期放入“关于”框中

    我有一个带有 关于 框的 C WinForms 应用程序 我使用以下方法将版本号放入 关于 框中 FileVersionInfo GetVersionInfo Assembly GetExecutingAssembly Location F
  • 当“int”处于最大值并使用 postfix ++ 进行测试时,代码定义良好吗?

    示例 未定义行为的一个示例是整数溢出的行为 C11dr 3 4 3 3 int溢出是未定义的行为 但这是否适用于存在循环的以下内容 并且不使用现在超出范围的副作用i 特别是 这是否后缀增量规格帮助 结果的值计算在副作用之前排序 更新操作数的
  • 在 C 中使用 GNU automake 中的解析器

    我是 GNU autotools 的新手 在我的项目中使用了 lex 和 yacc 解析器 将它们作为 makefile am 中的源代码会产生以下错误 配置 in AC CHECK PROGS YACC bison yacc none i
  • 当我“绘制”线条时,如何将点平均分配到 LineRenderer 的宽度曲线?

    我正在使用线条渲染器创建一个 绘图 应用程序 现在我尝试使用线条渲染器上的宽度曲线启用笔压 问题在于 AnimationCurve 的 时间 值 水平轴 从 0 标准化为 1 因此我不能在每次添加位置时都在其末尾添加一个值 除非有一个我不知
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • 在类的所有方法之前运行一个方法

    在 C 3 或 4 中可以做到这一点吗 也许有一些反思 class Magic RunBeforeAll public void BaseMethod runs BaseMethod before being executed public
  • 当前的 x86 架构是否支持非临时加载(来自“正常”内存)?

    我知道有关此主题的多个问题 但是 我没有看到任何明确的答案或任何基准测量 因此 我创建了一个处理两个整数数组的简单程序 第一个数组a非常大 64 MB 第二个数组b很小 无法放入 L1 缓存 程序迭代a并将其元素添加到相应的元素中b在模块化
  • 双精度类型二维多维数组的 pinvoke 编组作为 c# 和 c++ 之间的输入和输出

    我有以下我正在尝试解决的双物质类型的 2d 多维数组的 c 和 c pinvoke 编组 我已经查看了以下热门内容以获得我目前拥有的内容使用双精度数组进行 P Invoke 在 C 和 C 之间编组数据 https stackoverflo
  • 带重定向标准流的 C# + telnet 进程立即退出

    我正在尝试用 C 做一个 脚本化 telnet 项目 有点类似于Tcl期望 http expect nist gov 我需要为其启动 telnet 进程并重定向 和处理 其 stdin stdout 流 问题是 生成的 telnet 进程在
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 错误:无效使用不完整类型“类 Move”/未定义对 Move::NONE 的引用

    拜托 我不知道为什么这个简单的代码被拒绝 它给了我 2 个编译错误 请帮帮我 I use 代码 块 20 03 我的编译器是GNU GCC 移动 hpp class Move public Move Move int int public

随机推荐

  • Lisp 反转“全部”函数

    我想在 lisp 中编写一个函数 使用映射函数反转列表中的所有元素 但我不知道如何开始这个 我想我必须以某种方式使用内置的反向函数 例如 如果我有列表 1 2 3 4 5 6 7 8 9 我会得到 9 8 7 6 5 4 3 2 1 或者如
  • 如何在“--help”中定义单击子命令的顺序

    我有这样的代码 import click click group def entry point pass entry point add command lidtk data download documents main entry p
  • 网格上最长的路径,无需重新访问网格单元

    我正在寻找一种算法来找到网格上两点之间的最长路径 但附加的限制是您不能重新访问网格上的单元格 此外 您只能向上 向下 向左 向右移动 考虑到这些限制 我认为走最长的路径与尝试填充尽可能多的空间相同 然而 我在弄清楚如何做到这一点方面遇到了一
  • 在 SSRS 的一张图表中使用 2 个数据集

    是否可以拥有 2 个数据集并在 SSRS 报告的一张图表中显示它们的数据 还是我需要合并这些数据集 我在一个数据集中有已接听的电话数量 在另一个数据集中有未接的电话数量 我想在图表中显示它们 数据保存在不同的区域 这就是为什么我没有一开始就
  • 在圆圈内创建三个垂直点(省略号)

    我想做一个圆圈 div 就像这张图片 我已经尝试过这段代码 discussion after content 2807 font size 1em background 2d3446 width 20px height 20px borde
  • adb 无法连接到 tcp:5037 的守护进程

    我的 adb 无法连接设备 我在跑步adb start server ulucudeMacBook Pro ulucu adb start server daemon not running starting it now at tcp 5
  • 如何在已安装的 PWA 应用程序上推送应用程序更新?

    我的问题是 用户是否可以在无需重新安装 PWA 应用程序的情况下获取这些更改 我在生产中部署了一个 PWA 应用程序 客户端已在其移动设备中安装了已部署的 PWA 应用程序 我想在 HTTP 服务器中的 PWA 应用程序中部署另一个更新补丁
  • 使用 sed、awk、tr 和朋友删除尾随/开始换行符

    我想从文件中删除所有空行 但仅当它们位于文件的末尾 开头时 也就是说 如果它们之前没有非空行 则在开头 并且如果有最后 其后没有非空行 除了 Perl 或 Ruby 等功能齐全的脚本语言之外 这是否可能 我更愿意这样做sed or awk如
  • Haskell:检查两个列表是否相等

    我想检查是否有两个列表A and B是相等的 即a1 b1 a2 b2 我有一个可行的解决方案 all x gt x zipWith A B 另一个想法是递归地执行 a as b bs 检查是否a1 b1并使用剩余列表调用该函数as and
  • 在超类中缓存属性

    例如 我有一个类可以缓存一些值以避免多次计算它们 class A object def init self a b self a a self b b self value None property def value self if s
  • Github 创建带有 2 因素身份验证的令牌

    我正在尝试授权用户并取回令牌 用户已启用两因素身份验证 这是我尝试使用的代码 它不会接受我通过短信获得的代码 如果用户未启用 2fa 则此方法有效 curl i u user H X GitHub OTP code d scopes rep
  • 带中继的 TypeScript:无法解析生成的模块

    In my MessageItem tsx组件我有以下代码 const data useFragment graphql fragment MessageItem message on Message date body message a
  • spaCy 共指解析 - 命名实体识别 (NER) 返回唯一实体 ID?

    也许我跳过了部分文档 但我试图确定标准 NER 工具集中每个实体的唯一 ID 例如 import spacy from spacy import displacy import en core web sm nlp en core web
  • 如何使用webcal协议

    我想创建一个文件 可以使用webcal 协议 最终目标是让用户订阅共享日历 我知道这可以通过一百万种不同的方式来完成 而且webcal有缺点 但请将此问题视为技术问题webcal并且不提供替代方案 如果我希望它允许用户订阅共享日历 其内容应
  • 使用“如果单元格包含#N/A”作为公式条件。

    我需要有关 Excel 工作表的帮助 我如何声明以下内容IF状态正常吗 if A1 n a then C1 B1 else if A1 n a or has value int then C1 A1 B1 在中输入以下公式C1 IF ISN
  • 谷歌分析帐户ios配置

    我正在尝试配置谷歌分析GoogleService info plist文件来自谷歌开发者网站 https developers google com mobile add 昨天我配置了一个应用程序 没有出现任何问题 但今天我无法配置我的第二
  • 如何构建混合阵列

    在 ruby 中 我可以创建充满类型的数组 1 hello world Fixnum String Symbol gt 1 hello here Go中如何实现类似的数组填充混合类型 如何声明数组 您可以通过空界面来做到这一点 interf
  • 拖动时自动滚动可放置的 div

    在这个小提琴中 http jsfiddle net adrianjsfiddlenetuser zyUkd 76 http jsfiddle net adrianjsfiddlenetuser zyUkd 76 没有粉红色背景颜色的按钮可以
  • 随机生成器和 CUDA

    我有一个关于 CUDA 中的随机生成器的问题 我使用 Curand 生成随机数 代码如下 device float priceValue int threadid unsigned int seed threadid curandState
  • 条件属性如何工作?

    我有一些标记为的辅助方法 Conditional XXX 目的是在仅存在 XXX 条件编译符号时使方法进行条件编译 我们使用它来调试和跟踪功能 并且效果很好 在我研究条件编译如何工作的过程中 我发现了几个资料来源 说明了标记有Conditi