我试图测试一段简单的代码,涉及将常量名称乘以 20 但是我注意到当我输入带有常量的代码时遇到了问题:
void test() { const String name = "Foo"; const String nameTimes20 = name * 20; print(nameTimes20); }
与带有最终变量的代码相比:
final String name = "Foo"; final String nameTimes20 = name * 20;`
我很好奇为什么我需要使用 Final 变量而不是 const,因为操作所需的所有信息在编译时都可用。
String.operator*
不是允许的常量表达式。
Dart 有一个操作列表及其操作数的类型,这些操作允许是常量,而 string * int
不在该列表中。
这是可以允许的,这样做没有技术问题,编译器可以轻松地计算出结果应该是什么,而无需运行任何用户代码。
不允许该操作的一个原因是它允许在编译时分配任意大字符串。 Dart 常量仅限于与源代码大小呈线性关系的分配。它无法分配一个包含比源代码中编写的元素更多的元素的列表。 (这并不完全正确,同样是因为字符串,因为
String.operator+
是一个有效的常量运算,你可以执行 const v1 = "ab", v2 = v1+v1, v3 = v2+v2, .... , v10=v9+v9;
并创建一个与源代码大小呈指数关系的字符串。所以不要这样做。它还更多比var v20 = "ab" * 1048576;
)工作
另一件事是,它也可能是一个“潜在常量”表达式,可在常量构造函数中使用,因此您可以编写:
class Foo {
final String v;
const Foo(String s, int n) : v = s * n;
}
这可能导致进行大量分配,而无法看到写入大数字的操作。
因此,这是不允许的,这是为了您自己的保护(防止
其他人创建多兆字节的常量字符串,从而减慢您的编译速度)。