带[Conditional("RELEASE")]的类库方法在Debug构建中仍被调用问题
我在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项目中测试时一切正常,但将类库打包上传至私有GitHub NuGet源后,调用SetLaunchCount始终抛出异常,堆栈跟踪显示调用了ThrowOnReleaseBuild方法。
我已确认Debug构建确实包含DEBUG符号(且无RELEASE符号),还通过添加Debug.WriteLine方法验证了这一点。查看Debug.WriteLine的反编译源码,其实现方式与我的方法一致,但代码无法正常工作。
补充信息:
- 类库通过Release配置构建。
- 此前关于Conditional的解决方案现已失效。
解决方案
核心原因
你用Release配置构建类库时,编译器会基于类库自身的构建符号(而非引用项目的符号)处理Conditional特性。也就是说,类库在Release模式下编译时,自身定义了RELEASE符号,所以ThrowOnReleaseBuild方法的调用会被保留在编译后的程序集中。当引用该NuGet包的项目以Debug模式运行时,调用这个方法就会触发异常——因为类库编译后的代码里已经包含了这个调用,不会因为引用项目的符号而移除。
修正方案
要实现“仅在引用项目的Release构建中触发检查”,可以采用以下两种方式:
- 反转Conditional特性的符号,重载方法
[Obsolete("This method is for debugging only. Remove all calls to this method once done.")] public void SetLaunchCount(int count) { ThrowIfNotDebugBuild(); launchEntry.Set(count); } [Conditional("DEBUG")] static void ThrowIfNotDebugBuild() { // 空方法,仅在DEBUG构建中保留调用(无实际操作) } [Conditional("RELEASE")] static void ThrowIfNotDebugBuild() { throw new InvalidOperationException("This method must not be called outside of DEBUG build"); }
引用项目为Debug构建时,会调用空方法;为Release构建时,会调用抛出异常的版本,完全适配引用项目的构建模式。
- 直接使用编译指令控制代码
[Obsolete("This method is for debugging only. Remove all calls to this method once done.")] public void SetLaunchCount(int count) { #if RELEASE throw new InvalidOperationException("This method must not be called outside of DEBUG build"); #endif launchEntry.Set(count); }
这种方式让引用项目在编译时,根据自身的构建符号决定是否包含异常抛出代码,完全不受类库构建配置的影响。
为什么Debug.WriteLine能正常工作?
Debug.WriteLine所在的类库(如System.Diagnostics.Debug)是针对不同构建符号发布了适配版本,或是通过#if DEBUG编译指令而非Conditional特性实现逻辑,因此能自动适配引用项目的构建模式。
内容的提问来源于stack exchange,提问作者Luke Vo

