C#asp.net将具有long属性的对象传递到前端会更改它';s值
我正在构建一个带有react.js前端(尽管我相当确定这与问题无关)和asp.net后端(针对net5.0,不确定是否相关)的应用程序。当我调用后端API时,我得到一个对象,该对象部分包括它根据传入的数据生成的ID,该ID的类型为C#中的long(64位int)。我看到的行为是,C#中的变量和从前端响应读取的变量是不同的。它们似乎在大约16-17位之后漂移 这是预期的吗?有什么办法绕过它吗 复制我看到的内容/图片的代码: C# 控制台输出:C#asp.net将具有long属性的对象传递到前端会更改它';s值,c#,asp.net,asp.net-core,.net-5,C#,Asp.net,Asp.net Core,.net 5,我正在构建一个带有react.js前端(尽管我相当确定这与问题无关)和asp.net后端(针对net5.0,不确定是否相关)的应用程序。当我调用后端API时,我得到一个对象,该对象部分包括它根据传入的数据生成的ID,该ID的类型为C#中的long(64位int)。我看到的行为是,C#中的变量和从前端响应读取的变量是不同的。它们似乎在大约16-17位之后漂移 这是预期的吗?有什么办法绕过它吗 复制我看到的内容/图片的代码: C# 控制台输出:ID在C#控制器方法:92233720306530550
ID在C#控制器方法:9223372030653055062
Chrome开发工具:
当我试图访问前端的ID时,我得到了错误的ID,以000而不是062结尾
编辑1:有人建议这是因为JavaScript的Number.MAX\u SAFE\u INTEGER
小于我传递的值。我不相信这是原因,但也许我错了,有人可以启发我。在JS方面,我使用的是BigInt
,正是因为我传递的数字对于number
来说太大了。问题是在我将结果解析为JS对象之前(除非Chrome自动这样做,导致问题中引用的图片)
编辑2:根据下面的答案,在我将值解析为BigInt之前,JS可能正在将值解析为一个数字,所以我仍然在丢失精度。更熟悉网络的人能证实这一点吗?JavaScript引擎(显然)无法创建这么大的数字。尝试打开控制台并输入以下内容:
var myLong=9223372030653055062;
console.log(myLong)代码>JavaScript将该值解释为一个64位浮点数。如果要保留该值,最好将其作为字符串传递回去
示例JS演示问题:
var值=9223372030653055062;
console.log(值);
console.log(type of(value))代码>Javascript中数字的最大大小为2^53-1,即9007199254740991。在C#a long是2^64-1,这更大。所以“9223372030653055062”可以作为C#long,但不能作为JavaScript数字,因为它太大了。如果这个ID在使用long的数据库中使用,我建议您将它作为字符串传递给JavaScript。尽管原因是这个数字比JS能够准确表示的要大,但您似乎被Chrome的开发工具预览分散了注意力。这只是一个“有用的”预览,不一定是事实
dev工具预览显示了响应的有用视图。我假设AJAX响应是使用application/json的内容类型传输的,因此Chrome将json解析为JS对象并让您预览响应。检查Response选项卡,这是AJAX代码实际接收到的内容
很有可能在您有机会对该数字使用BigInt
之前就已经解析了JSON,从而限制了精度。您还没有向我们展示您的AJAX代码,所以这是我最好的猜测
唯一的解决方案是将其序列化为字符串,然后添加手动步骤将字符串转换为BigInt
jsObject.generatedId = BigInt(jsObject.generatedId);
如果您使用它作为ID,那么您最好将其作为字符串保存在客户端,因为您不可能使用它进行任何计算。我认为这是Javascript或Json格式的一个限制,您可以使用字符串而不是长字符串吗?long.Parse()
是最慢的方法。使用9223372030000000+rand。下一步(int.MaxValue)
同时,重新使用随机实例(使其成为静态成员)。这不仅是一个性能优化不足的问题,还可以确保您不会意外地使用同一个种子。@JoelCoehoorn忽略了实际的逻辑。这并不是ID的实际生成方式,只是一种说明问题的方法。在实际公式中没有Random()用法。@phuzi我编辑了我的问题,说我在前端使用BigInt,但也许JS仍然使用Number?我还不太熟悉web开发。如果在您有机会使用BigInt之前将响应解析为JS对象,那么该数字将已经转换为reglar JS数字,精度将降低。您可以调试AJAX请求/响应来确认这一点。是否没有办法告诉JS使用BigInt(据我推测,BigInt应该用Number来解决问题)?我很确定没有办法阻止浏览器这样做。OP的号码是9223372030653055000,远远大于您在9007199254740991时所声明的号码的最大值,使得号码的最大大小比2^53-1大得多
jsObject.generatedId = BigInt(jsObject.generatedId);