Csharp/C#教程:当任何数学运算在.net 4中产生’NaN’时,如何强制C#编译器抛出exception?分享


当任何数学运算在.net 4中产生’NaN’时,如何强制C#编译器抛出exception?

我有一个很复杂的源代码,我需要找到变量值设置为nan的确切位置。 所以我需要编译器在那时抛出一个exception。 之前已经问过这个问题。 我发现以下答案是一个很好的答案。 此代码在.net 3.5中运行良好。但是当我使用.net 4时,此解决方案无法正常工作。 即使我在调试器中启用“抛出exception时中断”,也无法在代码中找到exception。 任何的想法?

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace ConsoleApplication2 { class Program { [System.Runtime.InteropServices.DllImport("msvcrt.dll")] public static extern uint _control87(uint a, uint b); [System.Runtime.InteropServices.DllImport("msvcrt.dll")] public static extern uint _clearfp(); static void Main(string[] args) { float zero = 0.0f - args.Length; // Want 0.0f. Fool compiler... System.Console.WriteLine("zero = " + zero.ToString()); // A NaN which does not throw exception float firstNaN = zero / 0.0f; System.Console.WriteLine("firstNaN= " + firstNaN.ToString()); // Now turn on floating-point exceptions uint empty = 0; uint cw = _control87(empty, empty); // Debugger halts on this one and complains about false signature, but continue works. System.Console.WriteLine(cw.ToString()); uint MCW_EM = 0x0008001f; // From float.h uint _EM_INVALID = 0x00000010; // From float.h (invalid corresponds to NaN // See https://www.fortran-2000.com/ArnaudRecipes/CompilerTricks.html#x86_FP cw &= ~(_EM_INVALID); _clearfp(); // Clear floating point error word. _control87(cw, MCW_EM); // Debugger halts on this one and complains about false signature, but continue works. System.Console.WriteLine(cw.ToString()); // A NaN which does throw exception float secondNaN = 0; try { // Put as much code here as you like. // Enable "break when an exception is thrown" in the debugger // for system exceptions to get to the line where it is thrown // before catching it below. secondNaN = zero / 0.0f; } catch (System.Exception ex) { _clearfp(); // Clear floating point error word. } System.Console.WriteLine("secondNaN= " + secondNaN.ToString()); } } } 

发现了问题。 修改调用以使用_controlfp而不是_control87 ,然后将DllImport更改为:

 [System.Runtime.InteropServices.DllImport("msvcrt.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)] public static extern uint _controlfp(uint a, uint b); [System.Runtime.InteropServices.DllImport("msvcrt.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)] public static extern uint _clearfp(); 

您必须明确告诉.NET必须使用Cdecl约定调用您的方法。 然后它工作。 下次请写完整的exception……完整的消息应该是:

对PInvoke函数’_controlfp’的调用使堆栈失衡。 这很可能是因为托管的PInvoke签名与非托管目标签名不匹配。 检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

或者你可以作弊:-)

 struct DoubleNoNan { public readonly double Value; public DoubleNoNan(double value) { if (Double.IsNaN(value)) { throw new Exception("NaN"); } this.Value = value; } public static implicit operator double(DoubleNoNan value) { return value.Value; } public static implicit operator DoubleNoNan(double value) { return new DoubleNoNan(value); } public override bool Equals(object obj) { return this.Value.Equals(obj); } public override int GetHashCode() { return this.Value.GetHashCode(); } public override string ToString() { return this.Value.ToString(); } } 

然后:

 DoubleNoNan dn = 0.0; dn = / 0.0; 

对于float ,将Double替换为Single ,将double替换为float 。 操作符将由隐式强制转换提供。

显然它有其局限性(它不能用于ref / out表达式,以及许多其他表达式)

你的代码似乎工作正常……我已经检查了32位和64位

上述就是C#学习教程:当任何数学运算在.net 4中产生’NaN’时,如何强制C#编译器抛出exception?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/958131.html

(0)
上一篇 2021年11月22日
下一篇 2021年11月22日

精彩推荐