在Dart中检测何时将常量对象传递给对其进行变异的函数

在Dart中检测何时将常量对象传递给对其进行变异的函数,dart,constants,Dart,Constants,举个例子: 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.ba

举个例子:

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);
}
允许它工作


这对我来说似乎是一个错误,因为常量变量可以变异,dart可以在运行时检测到这一点,这意味着它可以检测何时修改常量对象,但这不应该在编译时检测到,因为常量变量被称为“编译时常量”

如果这不是一个bug,dart中是否有任何东西允许我们在编译时检测
const
变量是否可能被操作变异


在C++中,当我们尝试这样做时,编译器会出错。我们可以在Dart中做些什么来避免在运行时遇到此错误吗?

否。Dart
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 <代码>”是对象的属性,或者,实际上是对象创建的方式。这可能会对该对象产生一些后果。

constfoo(…)
只创建一个普通的
Foo
对象,但它只能创建深度不可变的对象,并且它们是规范化的。
const[…]
const{…}
创建的列表/映射/集与非常量文本不同,但在类型中不可见

在C++中,<<代码> const 是对象引用的属性,它限制了如何使用引用,但没有这样的常量对象。任何对象都可以作为
const
引用传递


这两个概念在本质上完全不同,只是碰巧使用了相同的名称(也都不同于JavaScript
const
)。

否。Dart
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 <代码>”是对象的属性,或者,实际上是对象创建的方式。这可能会对该对象产生一些后果。

constfoo(…)
只创建一个普通的
Foo
对象,但它只能创建深度不可变的对象,并且它们是规范化的。
const[…]
const{…}
创建的列表/映射/集与非常量文本不同,但在类型中不可见

在C++中,<<代码> const 是对象引用的属性,它限制了如何使用引用,但没有这样的常量对象。任何对象都可以作为
const
引用传递


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

您所说的一切都是有意义的,我理解这一点。即使在C++中,const也是编译时的特性,正如“任何变量都可以有一个常量”,这在C++中也是一样的。我的问题是为什么dart编译器没有完全强制执行变量的常量,即当对象被传递给一个可以修改它的函数时,是否有任何方法提示编译器这样做。@smac89与dart不同,C++有一个概念:代码> const t*< /C>和<代码> const t/< /c> >类型和 const 方法,声明函数不突变对象。请注意,这与对象本身是否为常量不同。@jamesdlin说的。我会把它添加到答案中。你所说的一切都有道理,我理解这一点。即使在C++中,const也是编译时的特性,正如“任何变量都可以有一个常量”,这在C++中也是一样的。我的问题是,为什么dart编译器没有完全强制执行变量的常量,即当对象被传递给一个可以修改它的函数时,有没有办法提示编译器这样做。@SMACK
var foo = const Foo([1,2,3,4]);