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 教程。