This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void main() { | |
print(const [null, 3] is List<int>); | |
print([null, 3] is List<int>); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Here's another pattern that `late` can | |
// help with: lazy initialization for | |
// expensive non-nullable fields. | |
// | |
// Try running this code without changing | |
// it. What do you think will change if | |
// you make `_cache` a `late` field? | |
int _computeValue() { | |
print('Computing value...'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The `late` keyword can be really helpful | |
// for tricky patterns like circular | |
// references. Here are two objects that | |
// need to maintain non-nullable references | |
// to each other. Try using the `late` | |
// keyword to fix this code. | |
class Team { | |
final Coach coach; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Sometimes fields in a class *should* be | |
// non-nullable, but can't be assigned a | |
// value right away. For cases like that, | |
// use the `late` keyword. It's a way to | |
// tell Dart that: | |
// | |
// * You aren't going to assign that | |
// field a value right away. | |
// * But you *are* going to assign it a | |
// value later. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// If you'd like to assign a nullable expression | |
// to a variable that's non-nullable, you can use | |
// the assertion operator (the exclamation point: | |
// `!`). By adding `!` just after the expression, | |
// you tell Dart that the value won't be null, | |
// and it's safe to assign to a non-nullable | |
// variable. | |
// | |
// Note: if you're wrong, an exception will be | |
// thrown! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Promotion works with exceptions as well | |
// as return statements. Try a null check | |
// that throws an `Exception` instead of | |
// returning zero. | |
int getLength(String? str) { | |
// Try throwing here if `str` is null. | |
return str.length; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// With null safety, Dart takes null checks | |
// into account. Nullable variables that | |
// can't possibly contain null are treated | |
// like non-nullable variables. | |
// | |
// This behavior is called "promotion." | |
// | |
// In the example below, add an if-then to | |
// the beginning of `getLength` that | |
// returns zero if `str` is null. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Conditional access is a handy way to | |
// tighten up code that needs to read | |
// properties that could be null: | |
// | |
// a?.b | |
// | |
// The expression above evaluates to the | |
// value of `b` as long as `a` isn’t | |
// null. If `a` is null, then the expression | |
// evaluates to null. Try using conditional |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Dart's type system is crafty enough to track | |
// where variables are assigned and where their | |
// values are read, and to verify that | |
// non-nullable fields are given values | |
// before any code tries to read from them. | |
// | |
// This process is called "definite assignment." | |
// | |
// Try uncommenting the if-else statement in the | |
// code below, and watch the analyzer errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Type parameters for generics can also be nullable or | |
// non-nullable. Try using question marks to correct the | |
// type declarations of `aNullableListOfStrings` and | |
// `aListOfNullableStrings`: | |
void main() { | |
List<String> aListofStrings = ['one', 'two', 'three']; | |
List<String> aNullableListOfStrings; | |
List<String> aListofNullableStrings = ['one', null, 'three']; | |