Dart UnmodifiableListView
最后修改于 2025 年 4 月 4 日
在 Dart 中,UnmodifiableListView 是 List 的一个不可修改视图。它包装了一个现有的 List,并阻止通过该视图进行修改。
UnmodifiableListView 实现 List 接口,但对于会修改列表的操作会抛出 UnsupportedError。它对于安全地暴露内部列表非常有用。
创建 UnmodifiableListView
创建 UnmodifiableListView 的最简单方法是使用其构造函数。
import 'dart:collection'; void main() { var numbers = [1, 2, 3, 4, 5]; var unmodifiableView = UnmodifiableListView(numbers); print(unmodifiableView); try { unmodifiableView.add(6); // Will throw } catch (e) { print('Error: $e'); } }
我们创建了一个可变列表的不可修改视图。尝试修改它会抛出 UnsupportedError。原始列表仍然可以修改。
$ dart main.dart [1, 2, 3, 4, 5] Error: Unsupported operation: Cannot add to an unmodifiable list
UnmodifiableListView 与 List 操作
UnmodifiableListView 支持所有非修改性 List 操作,例如访问和迭代。
import 'dart:collection'; void main() { var fruits = ['apple', 'banana', 'orange']; var unmodifiableFruits = UnmodifiableListView(fruits); // Access elements print('First fruit: ${unmodifiableFruits[0]}'); print('Length: ${unmodifiableFruits.length}'); // Iteration for (var fruit in unmodifiableFruits) { print(fruit.toUpperCase()); } // Non-modifying methods print('Contains apple: ${unmodifiableFruits.contains('apple')}'); print('Index of banana: ${unmodifiableFruits.indexOf('banana')}'); }
我们演示了 UnmodifiableListView 上的只读操作。所有标准的 List 访问方法都按预期工作,但不具备修改功能。
$ dart main.dart First fruit: apple Length: 3 APPLE BANANA ORANGE Contains apple: true Index of banana: 1
保护内部列表
UnmodifiableListView 通常用于安全地暴露内部列表。
import 'dart:collection'; class Team { final List<String> _members = []; UnmodifiableListView<String> get members => UnmodifiableListView(_members); void addMember(String name) { _members.add(name); } } void main() { var team = Team(); team.addMember('Alice'); team.addMember('Bob'); print('Team members: ${team.members}'); try { team.members.add('Charlie'); // Will throw } catch (e) { print('Cannot modify: $e'); } }
Team 类通过 UnmodifiableListView 公开其成员。客户端可以读取但不能直接修改列表。修改必须通过 addMember 进行。
$ dart main.dart Team members: [Alice, Bob] Cannot modify: Unsupported operation: Cannot add to an unmodifiable list
UnmodifiableListView 与 Unmodifiable List 的区别
UnmodifiableListView 与创建真正的不可修改列表不同。
import 'dart:collection'; void main() { var original = [1, 2, 3]; var view = UnmodifiableListView(original); var unmodifiableCopy = List.unmodifiable(original); original.add(4); // Modifies the original print('View: $view'); // Reflects changes print('Copy: $unmodifiableCopy'); // Doesn't change try { view.add(5); // Throws unmodifiableCopy.add(5); // Also throws } catch (e) { print('Both prevent modification'); } }
UnmodifiableListView 是一个实时视图,反映了对原始列表的更改。List.unmodifiable 创建一个独立的副本,该副本不会改变。
$ dart main.dart View: [1, 2, 3, 4] Copy: [1, 2, 3] Both prevent modification
与其他集合结合使用
UnmodifiableListView 可以与其他集合操作结合使用。
import 'dart:collection'; void main() { var data = [10, 20, 30, 40, 50]; // Create filtered unmodifiable view var evenView = UnmodifiableListView( data.where((n) => n % 2 == 0).toList()); print('Even numbers: $evenView'); // Create transformed unmodifiable view var squaredView = UnmodifiableListView( data.map((n) => n * n).toList()); print('Squared numbers: $squaredView'); // Attempt modification try { evenView.removeLast(); } catch (e) { print('Cannot modify: $e'); } }
我们通过结合过滤和映射与 UnmodifiableListView 来创建专门的不可修改视图。这些视图在显示转换后的数据时保持不变。
$ dart main.dart Even numbers: [20, 40, 50] Squared numbers: [100, 400, 900, 1600, 2500] Cannot modify: Unsupported operation: Cannot remove from an unmodifiable list
最佳实践
- 防御性编程: 用于防止意外修改。
- 性能: 可能的情况下,优先于复制大型列表。
- 文档: 清楚地表明 API 何时返回不可修改的视图。
- 替代方案: 考虑 List.unmodifiable 以获得真正不可变快照。
来源
本教程通过实际示例介绍了 Dart 的 UnmodifiableListView,演示了其关键功能和用法模式。
作者
列出 所有 Dart 教程。