Home > Back-end >  Freezed @Default list parameter creates unmodifiable list
Freezed @Default list parameter creates unmodifiable list

Time:07-03

I am trying out the example given in the Freezed page at https://pub.dev/packages/freezed. This is the example I am testing replacing int with List<int> adding a [40] as default.

@Freezed(makeCollectionsUnmodifiable: false)
class Example with _$Example {
  factory Example([@Default([40]) List<int> list]) = _Example;

  factory Example.fromJson(Map<String, dynamic> json) => _$ExampleFromJson(json);
}

using the Example class:

final e = Example();  //default parameter [40]
//e.list.add(42);     //error producing line
print('e $e');

final f = Example([40]); //parameter same as default value
f.list.add(42);
print('f $f');
    
final g = Example([41]); //another parameter
g.list.add(42);
print('g $g');

The output is:

e Example(list: [40])
f Example(list: [40, 42])
g Example(list: [41, 42])

If I remove the comment in the default parameter case, I get the following error:

Unhandled exception:
Unsupported operation: Cannot add to an unmodifiable list
#0      UnmodifiableListMixin.add (dart:_internal/list.dart:114:5)
#1      main (file:///D:/Dart/darttest/bin/darttest.dart:27:10)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#3      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

Why the list becomes unmodifiable?

CodePudding user response:

Dart annotations are used by code generators that parse the source code. As the expressions inside annotations do not get executed, they must be constant expressions that can be computed during compilation.

Objects constructed with the const keyword must be immutable. They cannot change, as is written in the Dart Language Tour:

You can’t change the value of a const variable:

baz = [42]; // Error: Constant variables can't be assigned a value.

Although a final object cannot be modified, its fields can be changed. In comparison, a const object and its fields cannot be changed: they’re immutable.

var constantList = const [1, 2, 3];
// constantList[1] = 1; // This line will cause an error.

To provide a default list value in the annotation, it must be const and therefore unmodifiable.

A note on Freezed

On another note, modifying lists goes against the entire Freezed concept. Freezed is used to generate immutable data structures, that can be updated with the copyWith method. It's a mistake to modify any collections in Freezed classes.

A recent update does add mutability through the unfreezed annotation, which should be used for mutable classes.

  • Related