Skip to content

Commit bc31e98

Browse files
committed
update rec for null check
1 parent a279976 commit bc31e98

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

examples/misc/lib/effective_dart/usage_good.dart

+7-1
Original file line numberDiff line numberDiff line change
@@ -350,19 +350,25 @@ class Response {
350350
String get reason => '';
351351
}
352352

353-
// #docregion shadow-nullable-field
353+
// #docregion shadow-nullable-field, null-check-promo
354354
class UploadException {
355355
final Response? response;
356356

357357
UploadException([this.response]);
358358

359359
@override
360360
String toString() {
361+
// #enddocregion null-check-promo
361362
final response = this.response;
362363
if (response != null) {
363364
return 'Could not complete upload to ${response.url} '
364365
'(error code ${response.errorCode}): ${response.reason}.';
365366
}
367+
// #docregion null-check-promo
368+
if (this.response case var response?) {
369+
return 'Could not complete upload to ${response.url} '
370+
'(error code ${response.errorCode}): ${response.reason}.';
371+
}
366372

367373
return 'Could not upload (no response).';
368374
}

src/content/effective-dart/usage.md

+38-10
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,8 @@ Of course, if `null` is a valid initialized value for the variable,
325325
then it probably does make sense to have a separate boolean field.
326326

327327

328-
### CONSIDER assigning a nullable field to a local variable to enable type promotion
328+
### CONSIDER work arounds to bypass type promotion limitations
329+
(or, "...to enable type promotion")
329330

330331
Checking that a nullable variable is not equal to `null` promotes the variable
331332
to a non-nullable type. That lets you access members on the variable and pass it
@@ -337,7 +338,31 @@ private final fields. Values that are open to manipulation
337338

338339
Declaring members [private][] and [final][], as we generally recommend, is often
339340
enough to bypass these limitations. But, that's not always an option.
340-
One pattern to work around this is to assign the field's value
341+
342+
One pattern to work around type promotion limitations is to use a
343+
[null-check pattern][] to simultaneously confirm the member's value is not null,
344+
and bind that value to a new non-nullable variable of the same base type.
345+
346+
<?code-excerpt "usage_good.dart (null-check-promo)"?>
347+
```dart tag=good
348+
class UploadException {
349+
final Response? response;
350+
351+
UploadException([this.response]);
352+
353+
@override
354+
String toString() {
355+
if (this.response case var response?) {
356+
return 'Could not complete upload to ${response.url} '
357+
'(error code ${response.errorCode}): ${response.reason}.';
358+
}
359+
360+
return 'Could not upload (no response).';
361+
}
362+
}
363+
```
364+
365+
Another work around is to assign the field's value
341366
to a local variable. Null checks on that variable will promote,
342367
so you can safely treat it as non-nullable.
343368

@@ -361,8 +386,16 @@ class UploadException {
361386
}
362387
```
363388

364-
Assigning to a local variable can be cleaner and safer than using `!` every
365-
time you need to treat the value as non-null:
389+
Be careful when using a local variable. If you need to write back to the field,
390+
make sure that you don't write back to the local variable instead. (Making the
391+
local variable [`final`][] can prevent such mistakes.) Also, if the field might
392+
change while the local is still in scope, then the local might have a stale
393+
value.
394+
395+
Sometimes it's best to simply [use `!`][] on the field.
396+
In some cases, though, using either a local variable or a null-check pattern
397+
can be cleaner and safer than using `!` every time you need to treat the value
398+
as non-null:
366399

367400
<?code-excerpt "usage_bad.dart (shadow-nullable-field)" replace="/!\./[!!!]./g"?>
368401
```dart tag=bad
@@ -383,15 +416,10 @@ class UploadException {
383416
}
384417
```
385418

386-
Be careful when using a local variable. If you need to write back to the field,
387-
make sure that you don't write back to the local variable instead. (Making the
388-
local variable [`final`][] can prevent such mistakes.) Also, if the field might
389-
change while the local is still in scope, then the local might have a stale
390-
value. Sometimes it's best to simply [use `!`][] on the field.
391-
392419
[can't be type promoted]: /tools/non-promotion-reasons
393420
[private]: /effective-dart/design#prefer-making-declarations-private
394421
[final]: /effective-dart/design#prefer-making-fields-and-top-level-variables-final
422+
[null-check pattern]: /language/pattern-types#null-check
395423
[`final`]: /effective-dart/usage#do-follow-a-consistent-rule-for-var-and-final-on-local-variables
396424
[use `!`]: /null-safety/understanding-null-safety#non-null-assertion-operator
397425

0 commit comments

Comments
 (0)