Dart int和double被拘留了?由相同的()专门处理?
Dart具有以下两种功能:Dart int和double被拘留了?由相同的()专门处理?,dart,identity,equality,object-identity,Dart,Identity,Equality,Object Identity,Dart具有以下两种功能: 相等运算符==和 名为idential()的顶级函数 通过语法的选择,想要比idential()更频繁地使用Dart的=操作符感觉很自然,我喜欢这样。事实上,最重要的是“实际上,您很少需要使用”idential() 在最近对的回答中,角度省道似乎倾向于在尝试确定模型更改是否达到稳定状态时使用idential(),而不是=。(我认为,出于效率考虑,这对于大型模型来说是有意义的。) 这让我想到了int的身份,所以我写了一些idential()对int的测试。虽然我预计
- 相等运算符
和==
- 名为
的顶级函数李>idential()
idential()
更频繁地使用Dart的=
操作符感觉很自然,我喜欢这样。事实上,最重要的是“实际上,您很少需要使用”idential()
在最近对的回答中,角度省道似乎倾向于在尝试确定模型更改是否达到稳定状态时使用idential()
,而不是=
。(我认为,出于效率考虑,这对于大型模型来说是有意义的。)
这让我想到了int
的身份,所以我写了一些idential()
对int
的测试。虽然我预计小的int
s可能会被“插入/缓存”(例如,类似于所做的),但令我惊讶的是,我似乎无法生成两个相等但不相同的int
s。对于double
,我得到了类似的结果
int
和double
值是否被缓存?或者可能是idential()
在特别对待他们?我来自Java背景,过去常常将Dart等同于:
到Java的==
方法和equal()
到Java的相等性测试idential()
==
但现在看来这是错误的。有人知道发生了什么吗?我记不起这件事的来源,但在dartlang.org或问题追踪网站上的某个地方,有人说
num
、int
和double
确实得到了特殊对待。其中一种特殊处理方法是,由于性能原因,您不能对这些类型进行子类化,但可能还有更多。这一特殊处理的具体内容可能只能由开发人员或熟记规范的人来回答,但可以推断出一件事:
数字类型是省道对象-它们具有可在其实例上调用的方法。但它们也具有原始数据类型的特性,就像您可以做的那样inti=3
,而纯对象应该在某个地方有一个new
关键字。这与Java不同,Java中有真正的原语类型和真正的对象包装它们并公开实例方法
虽然技术细节当然更复杂,但如果您将dart数字看作是对象和原语的混合体,那么您与Java的比较仍然是有意义的。在Java中,newinteger(5).equals(newinteger(5))
的计算结果为true,5==5
我知道这在技术上不是一个非常正确的答案,但我希望它对于理解来自Java背景的dart数字的行为仍然有用。似乎我发布得太快了。我刚刚偶然发现了Dart问题,这使我进入了上页的Dart部分。(我以前曾在规范中搜索相等,但没有搜索对象标识。) 以下是摘录:
The predefined dart function identical() is defined such that identical(c1, c2) iff:
- c1 evaluates to either null or an instance of
bool and c1 == c2, OR
- c1 and c2 are instances of int and c1 == c2, OR
- c1 and c2 are constant strings and c1 == c2, OR
- c1 and c2 are instances of double and one of the following holds: ...
还有更多的子句处理列表、映射和常量对象。有关详细信息,请参阅。因此,
idential()
不仅仅是一个简单的参考等式测试。数字是经过特殊处理的。如果它们的位模式相同,则它们必须相同(尽管这是否包括不同版本的NAN仍有争议)
主要原因是期望值、内部细节泄露和效率
期望值:用户期望数字相同。x==y(对于两个整数)但不相同(x,y),这违背了常识
泄漏内部详细信息:VM使用SMI(小整数)表示特定范围内的整数(32位机器上为31位,64位机器上为63位)。这些都是标准化的,并且总是相同的。根据您运行的平台,公开此内部实现细节将导致不一致的结果
效率:虚拟机希望尽可能地取消数字的装箱。例如,在一个方法中,double经常被移动到寄存器中。但是,跟踪原始框可能会很麻烦和困难
foo(x, y) {
var result = x;
while(y-- > 0) {
result += x;
}
return result;
}
假设虚拟机优化了这个函数,并将结果
移动到寄存器中(在过程中取消装箱x
)。这允许在结果
被有效修改的地方进行紧密循环。当y
为0时,就会出现困难的情况。循环不会执行,foo
将直接返回x
。换言之,必须做到以下几点:
var x = 5.0;
identical(x, foo(x, 0)); // should be true.
如果VM在方法foo
中取消了result
变量的绑定,它将需要为结果
分配一个新的框,因此相同的
调用将返回false
通过修改
相同的定义
可以避免所有这些问题。但是,对相同的检查来说,它的成本很小。相同的检查引用,==检查值是否相等。如果您在创建两个相同值但不相同的int时遇到问题,这意味着您的变量实际上共享相同的引用,如果您的编译器正在优化代码,并意识到这些值将完全相同,这是有意义的。您好,MarioP。你说得对,int
,double
等被特殊对待。我刚刚在语言规范中找到了证实这一点的部分。非常深入地了解了情况。谢谢虽然我很惊讶我的心智模型被抛弃了,但我更喜欢给定的Dart语义idential
。理论上,它甚至可以作为一种优化(例如在垃圾收集期间)。在一些JavaScri中