C# 代码在版本模式和调试模式下的行为不同

C# 代码在版本模式和调试模式下的行为不同,c#,.net,release,C#,.net,Release,我们有一些单元测试在发布模式和调试模式下运行时失败。如果在发布模式下附加调试器,测试将通过。这里有太多的代码要发布,所以我只是在寻找调试发布模式问题的最佳实践。我已经检查过: 调试和发布预处理器指令,但我没有找到任何指令 解决方案:在本例中,这是因为我在比较浮点变量是否相等。我无法在不进行重大重构的情况下将浮点更改为十进制,因此我添加了一个扩展方法: public static class FloatExtension { public static bool AlmostEqua

我们有一些单元测试在发布模式和调试模式下运行时失败。如果在发布模式下附加调试器,测试将通过。这里有太多的代码要发布,所以我只是在寻找调试发布模式问题的最佳实践。我已经检查过:

  • 调试和发布预处理器指令,但我没有找到任何指令
解决方案:在本例中,这是因为我在比较浮点变量是否相等。我无法在不进行重大重构的情况下将浮点更改为十进制,因此我添加了一个扩展方法:

public static class FloatExtension
{
    public static bool AlmostEquals(this float f1, float f2, float precision)
    {
        return (Math.Abs(f1 - f2) <= precision);
    }

    public static bool AlmostEquals(this float f1, float f2)
    {
        return AlmostEquals(f1, f2, .00001f);
    }

    public static bool AlmostEquals(this float? f1, float? f2)
    {
        if (f1.HasValue && f2.HasValue)
        {
            return AlmostEquals(f1.Value, f2.Value);
        }
        else if (f1 == null && f2 == null)
        {
            return true;
        }
        return false;
    }
}
公共静态类浮动扩展
{
公共静态布尔AlmostEquals(此浮点f1、浮点f2、浮点精度)
{

return(Math.Abs(f1-f2)可能导致您看到的行为的一件事是导致错误的错误。附加调试器可以更改代码的计时,从而不再触发争用条件

若要修复此问题,请在有多个线程访问数据时适当地使用同步


我正在比较等质量方法中的一些浮点值


这听起来是一个非常糟糕的主意。你不应该比较浮点数是否相等,因为浮点数计算不是100%精确的,你可能会得到表示和舍入错误。比较它们是否足够接近。对于涉及金钱的计算,你可能想改为使用
decimal
类型

正如Mark所建议的,这通常是与时间相关的问题造成的,通常是竞争条件或同步问题

处理此类问题的一种常见方法是在受影响的区域使用“打印”语句来显示正在发生的情况。如果打印语句(
Console.WriteLine
Response.Write
、日志记录或其他任何内容)解决问题,将值存储在全局变量中,并在问题出现后打印全局变量


我最近一次遇到这种情况是在从串行端口读取的代码中。调试活动引起的时间变化刚好足以影响串行端口字节的缓冲方式,从而改变了缓冲区的解析方式。由于print语句改变了时间,我不得不将数据存储到输出稍后。

你应该问自己的问题-

  • 我的代码是线程化的吗?计时差异会影响输出
  • 是否有人用一个会产生副作用的表达式调用Debug.Assert()
  • 哪些对象实现IDisposable(),有些对象实现IDisposable()的方式会改变状态
  • 您是否正在调用非托管代码
  • 在这种情况下,数字3很可能是一个坏孩子。在调试和发布中,垃圾收集可能非常不同,您可能会发现,当对象被垃圾收集时,会影响稍后单元测试的结果


    仅供参考,如果您使用NUnit和TestDriven.NET,这两种测试以不同的顺序运行。

    由于它似乎与浮点相关,因此可能会出现很多问题。请参阅: 和


    有太多的事情可以用浮点来处理。比较浮点是否相等是一个普遍的禁忌。你可以检查小于合理ε的差异。

    这通常是因为调试构建在默认情况下没有优化,即使你启用了它,调试时的行为也是非常不同的。你可以n从“属性->生成”选项卡上的所有程序集的项目设置中禁用“优化代码”

    当然还有其他的变化会导致差异,比如你提到的条件方法就是其中之一。我发现这些变化很少是问题的原因,对我来说,它几乎总是优化器

    优化器的经典gotcha包括“内联”方法,因此它们无法出现在调用堆栈上。这在使用System.Diagnostics.StackFrame类确定当前执行点时会导致问题。类似地,这将影响MethodBase.GetCurrentMethod或其他依赖exec的函数/行为的结果计算方法

    当然,我看到优化器做了很多我根本无法解释的事情。有一个这样的例子在一篇文章“”中被记录和讨论过,但我从来没有解开这个谜团。我只知道优化器在用于生成一系列派生字节时只是断掉了Rfc2898DeriveBytes。奇怪的是,只有在生成的字节不能被使用的哈希算法的大小(20)平均整除,并且只在前20个字节之后生成错误的结果


    事实上,优化对代码不利的影响并不是编译器的新事物。大多数老的C++开发者会直接告诉你,然后,就像我一样,进入一些关于他们是如何工作的冗长故事。

    为了增加我的两分钱,我最近发现我在测试调用的一个sql过程中进行了日期比较。这些日期都是在测试过程之前自动生成的,并且值被插入到数据库中,因此有时它们完全相同(当使用RunTests时)导致在表联接上返回null。这不是我所期望的。显然,在调试模式下,由于我正在缓慢地进行调试,自动生成的时间会有所不同,这意味着我从未遇到错误。我通过插入

    线程。线程。睡眠(520)


    无论什么地方,操作之间肯定会有延迟。问题已解决。

    两个问题。1.你会遇到什么样的失败,让问题变得有点“味道”?2.你检查过条件方法吗?主要问题是Equals方法返回false。但是,如果我单独使用每个语句,它们都会返回tr如果我尝试附加一个调试器,问题就会消失。是否与浮点相关(数据类型双精度等)?@M