在调试版本中仍调用 [Conditional(“RELEASE”)] 的 C# 库方法

C# library method with [Conditional("RELEASE")] still called in Debug build

提问人:Luke Vo 提问时间:8/21/2023 最后编辑:Luke Vo 更新时间:8/22/2023 访问量:54

问:

我有以下代码:MyLib.dll

    [Obsolete("This method is for debugging only. Remove all calls to this method once done.")]
    public void SetLaunchCount(int count)
    {
        ThrowOnReleaseBuild();
        launchEntry.Set(count);
    }

    [Conditional("RELEASE")]
    static void ThrowOnReleaseBuild()
    {
        throw new InvalidOperationException("This method must not be called outside of DEBUG build"); ;
    }

当我在同一解决方案中使用项目(在我的情况下为 MAUI)对其进行测试时,它工作正常。但是,在打包并将其上传到 Nuget(通过我们的私有 Github Nuget 源)时,调用总是抛出,堆栈跟踪显示对 .SetLaunchCountThrowOnReleaseBuild

我已经仔细检查过,调试版本确实有符号(更准确地说,没有符号):DEBUGRELEASE

enter image description here

我还尝试添加另一种方法来确认它:Debug.WriteLine

enter image description here

为什么它不起作用?例如,我检查了(反编译的)源代码,它的编码就像我的方法一样:Debug.WriteLine

        [Conditional("DEBUG")]
        public static void WriteLine(string? message) =>
            s_provider.WriteLine(message);

编辑:添加更多信息:

  • 该库是在 Release Profile 中构建的。

  • 请参阅我之前关于使用 .不知何故,它现在不起作用。Conditional

C# .NET 调试 条件编译

评论

0赞 Paweł Łukasik 8/22/2023
如果它抛出,则表示该包是使用“RELEASE”标志集编译的,并且代码在那里。NuGet 包中的二进制文件已编译,并且具有此方法。如果现在您在 DEBUG 中编译的其他代码中使用它,您的 dll 不会神奇地重新编译自身并且不会抛出。
0赞 Luke Vo 8/22/2023
@Pawe Łłukasik虽然没有意义,因为使用了相同的技术。虽然你是对的,但我忘了提到该库是用标志编译的。Debug.WriteLineRELEASE
0赞 Luke Vo 8/22/2023
@Pawe łłukasik 也请看这个答案作为参考
0赞 Paweł Łukasik 8/22/2023
我认为你弄错了答案。如果您直接调用该方法而不是通过其他方法,它将像这样工作。看看我的答案

答:

1赞 Paweł Łukasik 8/22/2023 #1

它按预期工作。从文档中,您可以阅读(强调我的)

将 ConditionalAttribute 应用于方法会向编译器指示,除非定义了与 ConditionalAttribute 关联的条件编译符号,否则不应将对该方法的调用编译为 Microsoft 中间语言 (MSIL)。

因此,当您使用 RELEASE 或 DEBUG 标志编译代码时,并不是说 里面的代码被删除了。电话本身不存在——这就是“它有效”的原因。Debug.WriteLineDebug.WriteLine

因此,就您而言: 在 DEBUG 模式下,该方法受到以下影响:SetLaunchCount

[Obsolete("This method is for debugging only. Remove all calls to this method once done.")]
public void SetLaunchCount(int count)
{
    ThrowOnReleaseBuild(); <-- this is removed in DEBUG, and not in RELEASE
    launchEntry.Set(count);
}

在发布模式下将其打包到 NuGet 中时,该方法就在那里,如果在 DEBUG 或 RELEASE 中编译代码,则不会影响它,因为调用标记为属性的方法的不是代码。你只叫.ConditionalSetLaunchCount

如果您将该方法公开并从您的代码中调用它,即使它在 Nuget 中 - 它也会按预期工作,因为对该方法的调用是否存在取决于条件。ThrowOnReleaseBuild

评论

1赞 Luke Vo 8/22/2023
是的,我也在考虑这个问题,似乎就是这样。我稍后将运行MSIL代码进行确认,但我认为你是对的。