Let’s examine some examples:
var intList = <int>[1, 2, 3];
var dynamicList = intList as List<dynamic>; // Works.
var intList2 = dynamicList as List<int>; // Works.
But:
var dynamicList = <dynamic>[1, 2, 3];
var intList = dynamicList as List<int>; // Fails at runtime.
What’s the difference?
In the first example, intList
has a static type of List<int>
, and the actual runtime type of the object is also List<int>
. dynamicList
has a static type of List<dynamic>
but has an actual runtime type of List<int>
(it’s the same object as intList
). Since the object was originally a List<int>
, it is impossible for the List
object to hold anything but int
elements, and casting back to List<int>
is safe.
In the second example, dynamicList
has a static type of List<dynamic>
and an actual runtime type of List<dynamic>
. Since the object is initially constructed as a List<dynamic>
, non-int
elements could have been added to it, and casting to List<int>
is not necessarily safe. You therefore instead must create a new List
(or List
-like) object that casts each element individually, which is exactly what List.from
and List.cast
do.