In Dart, collections like List, Set, and Map are mutable by default, meaning we can add, remove, or modify their elements after creation. However, Dart also provides ways to make them immutable (read-only) β which is useful for maintaining data integrity and preventing accidental changes, especially in state management or shared data scenarios.
Let me explain each case clearly:
1. Mutable Collections (Default Behavior)
Normally, when we create a List, Set, or Map, they are modifiable.
void main() {
var list = [1, 2, 3];
list.add(4); // β
Works
print(list); // [1, 2, 3, 4]
var set = {10, 20};
set.add(30); // β
Works
print(set); // {10, 20, 30}
var map = {'name': 'Aswini'};
map['age'] = 25; // β
Works
print(map); // {name: Aswini, age: 25}
}
2. Immutable Collections (Using const)
If we want a collection that cannot be modified after itβs created, we use the const keyword.
This makes the entire collection compile-time constant and unchangeable.
void main() {
const list = [1, 2, 3];
// list.add(4); β Error: Unsupported operation
const set = {10, 20, 30};
// set.remove(10); β Error
const map = {'key': 'value'};
// map['key2'] = 'new'; β Error
}
So, const makes the collection deeply immutable β neither the structure nor the values can change.
3. Read-only Views (Using unmodifiable constructor)
Sometimes, we may want to prevent modification at runtime, but we donβt know the values at compile-time.
For that, Dart provides List.unmodifiable(), Set.unmodifiable(), and Map.unmodifiable().
void main() {
var original = [1, 2, 3];
var unmodifiableList = List.unmodifiable(original);
// unmodifiableList.add(4); β Throws runtime error
}
This is especially helpful when you need to expose a collection publicly but want to protect it from modification externally β Iβve used this approach in Flutter projects where I had to expose lists of UI state but ensure widgets donβt accidentally mutate them.
4. Real-world example:
In a Flutter app managing state with Provider, I stored a list of products in a model class. To ensure no widget modified it directly, I returned it as List.unmodifiable(_products). That way, any changes had to go through proper setter methods β ensuring controlled updates.
Challenges faced:
One challenge was understanding that even if you make a List unmodifiable, the objects inside can still be mutable. For example, a List.unmodifiable of custom objects can still have their internal properties changed β so itβs not βdeep immutability.β
Limitations:
constcan only be used with compile-time constants.unmodifiableprevents structural changes but not internal object mutation.
Alternative:
If deep immutability is required, Iβve used data classes or packages like built_collection or freezed, which generate immutable models automatically β very useful for state management patterns like BLoC or Redux.
So, in summary:
Dart collections are mutable by default, but you can make them immutable using
constfor compile-time orunmodifiable()for runtime protection β ensuring safer and more predictable code.
