在Dart中检测何时将const对象传递给对其进行突变的函数 [英] Detecting when a const object is passed to a function that mutates it, in Dart

查看:120
本文介绍了在Dart中检测何时将const对象传递给对其进行突变的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以这个示例为例:

  void modl(List< int> l){
l.add(90);
print(l);
}

Foo类{
final List< int>酒吧;
const Foo(this.bar);

@override
字符串toString()=> ‘Foo {bar:$ bar}’;
}

void main(){
var foo = const Foo([1,2,3,4]);
modl(foo.bar);
print(foo);
}

运行上述代码会导致运行时 未捕获的错误,但从

  var中删除了 const  foo = const Foo([1,2,3,4]); 

允许它工作。




此对我来说似乎是个错误,因为const变量可以被更改并且dart在运行时可以检测到它,这意味着它可以检测const对象何时被修改,但是不应在编译时检测到它,将其视为const变量称为 编译时常量


如果这不是错误,那么dart中有什么可以让我们在编译时检测到的


在C ++中,当我们尝试执行类似这样的操作时,何时 const 变量可能会被操作突变?


这个。在Dart中我们可以做些什么来避免在运行时遇到此错误?

解决方案

否。 Dart const 是围绕对象创建的编译时功能,但未反映在类型系统中。
您不能从任何对象的类型来判断它是否是常量。


通常这不是问题,因为可以是 const不可修改。它不能保证完全不变,但是实例本身不能更改其字段。


列表,集合和映射既可以是常数也可以是可变的。这就是您在这里看到的。
const Foo(const [1,2,3,4])的列表参数是常量,即使您删除了多余的 const 在列表文字上。使用 new Foo(const [1、2、3、4])也会遇到相同的问题,它还会提供一个不可变的 foo.bar。 ,但与 new Foo([1、2、3、4])不能区别。唯一的实际区别是列表是否可修改,检测到列表的唯一方法是尝试对其进行修改。


列表,集合和映射不提供任何检测方法


与C ++相比,Dart的 const 概念是一个对象的属性,或者实际上是对象的创建方式。这可能会对对象产生一些后果。 const Foo(..)只会创建普通的 Foo 对象,但只能创建深度不变的对象,并且他们被规范化了。 const [...] const {...} 会创建另一种列表/地图/集合


在C ++中, const 是对象的属性,而不是非常量文字。引用,它限制了该引用的使用方式,但是没有这样的常量对象。任何对象都可以作为 const 引用传递。


这两个概念本质上是完全不同的,并且碰巧使用相同的概念名称(并且与JavaScript const 都不同)。


Take this example:

void modl(List<int> l) {
  l.add(90);
  print(l);
}

class Foo {
  final List<int> bar;
  const Foo(this.bar);

  @override
  String toString() => 'Foo{bar: $bar}';
}

void main() {
  var foo = const Foo([1,2,3,4]);
  modl(foo.bar);
  print (foo);
}

Running the above code results in a runtime Uncaught Error, but removing the const from

var foo = const Foo([1,2,3,4]);

allows it to work.


This seems like a bug to me because the const variable can be mutated and dart detects this at runtime, which means it has the means to detect when a const object is modified, but shouldn't this have been detected at compile time, seeing as const variables are called "compile-time constants".

If this is not a bug, is there anything in dart that allows us to detect at compile time when a const variable will possibly be mutated by an operation?

In C++, the compiler errors out when we try to do something like this. Is there anything we can do in Dart to avoid encountering this error at runtime?

解决方案

No. Dart const is a compile-time feature around object creation, but it's not reflected in the type system. You can't tell from the type of any object whether it's a constant or not.

Usually that's not a problem because an instance of a class which can be const is unmodifiable. It's not guaranteed to be deeply immutable, but the instance itself cannot have its fields changed.

Lists, sets and maps can both be either constant and mutable. That's what you are seeing here. The list argument to const Foo(const [1, 2, 3, 4]) is constant, even if you remove the redundant const on the list literal. You would have the same issue with new Foo(const [1, 2, 3, 4]), which would also provide an immutable foo.bar, but which would otherwise be indistinguishable from new Foo([1, 2, 3, 4]). The only real difference is whether the list is modifiable or not, and the only way to detect that is to try to modify it.

Lists, sets and maps do not provide any way to detect whether they are mutable or not except trying, and catching the error.

When comparing to C++, Dart's notion of being const is a property of the object or, really, the way the object is created. That may have some consequences for the object. A const Foo(..) just creates a normal Foo object, but it can only create deeply immutable objects, and they are canonicalized. A const [...] or const {...} creates a different kind of list/map/set than the non-const literal, but that's not visible in the type.

In C++, being const is a property of an object reference, and it restricts how that reference can be used, but there are no constant objects as such. Any object can be passed as a const reference.

The two concepts are completely different in nature, and just happen to use the same name (and are also both different from JavaScript const).

这篇关于在Dart中检测何时将const对象传递给对其进行突变的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆