I can't add/delete/modify elements in a const list and in an unmodifiable list. So, what's the difference between the two if they both are doing the same thing?
3 Answers
There is no difference because, slightly exaggerated, there is no "const list".
In Dart, being constant is not a property of a value, it's a property of an expression.
Example:
class Foo {
final int x;
const Foo(this.x);
}
main() {
var foo1 = const Foo(1);
var foo2 = new Foo(1);
print(isConstant(foo1)); // cannot be done.
}
There is no way to write a general isConstant
function which can distinguish an object created using const
from one created using new
.
The run-time system has a list of the const-created objects somewhere (because it needs that to canonicalize another const Foo(1)
to the same value), but the value itself doesn't know that it was created using a const
expression.
List literals are slightly different from constructor based object creation because a non-const literal is mutable and a const literal is not.
Instead the const
literal creates a list object similar to the one you would create using List.unmodifiable
.
And again, the list object itself doesn't know whether it was created using const [...]
or List.unmodifiable([...])
, it just knows that it's an unmodifiable list with a specific set of values.
The VM actually uses the same class for both const lists and unmodifiable lists (dart2js uses JS Array for everything, but does mark them the same way as fixed-length and unmodifiable). The compilers didn't have to use the same class, it's an implementation detail how const
lists are implemented, but it's also not surprising that they only have one implementation of an unmodifiable list, anything else would be wasteful.
So, there is no difference between a const list object and a list created using List.unmodifiable
. They're instances of the same implementation class.
(Obviously, a constant variable holding a constant list can be used in other constant expressions, and constant list literals are canonicalized, so if you write const [1]
two places in the program, it evaluates to the same list object, but the object itself is just an unmodifiable list).
Another important difference is two equal const
objects are guaranteed to be identical (so they points to the same internal object since the object is built on compile time) where two unmodifiable lists will always be two different objects:
void main() {
final unmodifiableList1 = List<int>.unmodifiable(<int>[1,2,3]);
final unmodifiableList2 = List<int>.unmodifiable(<int>[1,2,3]);
print(identical(unmodifiableList1, unmodifiableList2)); // false
const constList1 = [1,2,3];
const constList2 = [1,2,3];
print(identical(constList1, constList2)); // true
}
const
objects. – jamesdlin