Je mets à niveau un package personnel basé sur le framework Flutter. J'ai remarqué ici Dans le code source du widget de texte Flutter selon lequel il y a une vérification nul:
class MyClass { String? _myString; String get myString { if (_myString == null) { return ''; } return _myString; // <-- error here } }
Cependant, textSpan!
utilise toujours l'opérateur !
. Ne devrait-il pas être promu textSpan
en un type non nullable sans avoir à utiliser l'opérateur !
? Cependant, essayer de supprimer l'opérateur donne l'erreur suivante:
An expression whose value can be 'null' must be null-checked before it can be dereferenced. Try checking that the value isn't 'null' before dereferencing it.
Voici un exemple autonome:
if (textSpan != null) { properties.add(textSpan!.toDiagnosticsNode(name: 'textSpan', style: DiagnosticsTreeStyle.transition)); }
J'obtiens une erreur de compilation:
Erreur: une valeur de type 'String?' ne peut pas être renvoyé de la fonction «mystring» car il a un type de retour de «chaîne».
ou si j'essaie d'obtenir _mysting.length
j'obtiens l'erreur suivante:
La «longueur» de la propriété ne peut pas être accessible sans condition car le récepteur peut être «nul».
Je pensais que faire la vérification null favoriserait _mystring
à un type non nullable. Pourquoi n'est-ce pas?
ma question a été résolue sur github donc je poste une réponse ci-dessous.
3 Réponses :
L'ingénieur de dart Erik Ernst indique sur github :
La promotion de type ne s'applique qu'aux variables locales. ... La promotion d'une variable d'instance n'est pas solide, car elle pourrait être remplacée par un getteur qui exécute un calcul et renvoie un objet différent chaque fois qu'il est invoqué. Cf. dart-lang / langage # 1188 Pour les discussions sur un mécanisme similaire à type promotion mais basée sur des vérifications dynamiques, avec quelques liens vers des discussions connexes.
La promotion de type local fonctionne donc:
class MyClass { String? _myString; String myMethod() { if (_myString == null) { return ''; } return _myString!; } }mais les variables d'instance ne font pas la promotion. Pour cela, vous devez dire manuellement à Dart que vous êtes sûr que la variable d'instance n'est pas nul dans ce cas en utilisant l'opérateur
!
:String myMethod(String? myString) { if (myString == null) { return ''; } return myString; }p>
Peut être réécrit myMethod
comme string myMethod () {return _mystring ?? ''}
?
@GegoByte, oui (si vous ajoutez un point-virgule).
Disons, c'est votre code et vous faites une vérification nul sur la variable d'instance et en voyant toujours une erreur:
double bar() { return i!.toDouble(); // <-- Bang operator in play. }
La méthode «Todouble» ne peut pas être invoquée inconditionnellement car le récepteur peut être «nul».
L'erreur que vous voyez dans le code comme celle-ci est parce que les getters ne sont pas promus avec leurs homologues non nuls . Parlons de la raison.
Disons, il y a une classe bar
qui étend foo et remplacer
i
variable et ne lui attribue aucune valeur (en gardant null
):
double bar() { return i?.toDouble() ?? -1; // Provide some default value. }
Donc, si vous pouviez faire
double bar() { var i = this.i; // <-- Use of local variable. if (i != null) return i.toDouble(); return -1; }
, vous auriez rencontré une erreur nulle d'exécution, c'est pourquoi la promotion de type Getters est interdite.
Nous devons rejeter la nullabilité de int?
. Il existe généralement 3 façons de le faire (plus de façons d'inclure l'utilisation de comme
, est
, etc.)
Utilisez la variable locale (recommandée)
print(Bar().func() * 2);
utilisation ?. avec ??
class Bar extends Foo { @override int? i; }
Utilisez l'opérateur de bang (!)
Vous ne devez utiliser cette solution que lorsque vous êtes sûr à 100% que la variable ( i
) ne sera jamais null
.
class Foo { int? i = 0; double func() { if (i != null) return i.toDouble(); // <-- Error return -1; } }
La solution de variable locale ressemble à la meilleure option, surtout lorsque vous devez utiliser + = ou * = opérateurs
Détails sur la documentation: dart.dev/guides/language/language-tour#other- Opérateurs
La solution pour utiliser une variable locale est-elle votre recommandation personnelle, ou l'équipe DART a-t-elle dit quelque chose à ce sujet?
@ Hanneshultergård Il provient d'un article écrit par l'un des membres de l'équipe DART.
Veuillez me corriger si je me trompe, mais à moins que je ne manque à quelque chose de fondamental ici, je pense que cet exemple n'illustre pas vraiment le raisonnement derrière la prévention de la promotion Getter, puisque i
évidemment ne change jamais après le chèque nul. Ne serait-il pas un meilleur exemple pour i
dans bar
être int? obtenir i => random (). nextbool ()? 0: null;
comme celui montré ici ? De cette façon, vous pouvez vraiment voir comment le compilateur ne pourrait jamais garantir que i
n'est pas nul, car sa valeur peut passer à NULL lorsqu'elle est accessible après la vérification nul.
@Omarsharaki Oui, j'aurais dû changer l'exemple pour utiliser un bool
au lieu de int
qui ferait quelque chose comme ce que vous avez mentionné. Je pense que j'ai publié quelque part un code similaire.
Style: thème.of (Context) .TextTheme.headline5! .CopyWith (
style: Theme.of(context).textTheme.headline5!.copyWith( color: Colors.white
Essayez de rendre l'appel conditionnel en utilisant? Ou un vérificateur de sécurité nul -!
p>
Votre réponse pourrait être améliorée avec des informations de support supplémentaires. Veuillez modifier pour ajouter plus de détails, tels que des citations ou de la documentation, afin que d'autres puissent confirmer que votre réponse est correcte. Vous pouvez trouver plus d'informations sur la façon d'écrire de bonnes réponses dans le centre d'aide .
Il s'agit essentiellement d'une autre version de stackoverflow.com/q/56764592 (Je suis sûr qu'il y a aussi d'autres questions existantes).
@jamesdlin, c'est intéressant. Je ne savais pas que c'était plus généralisé que la sécurité nul.
Je l'ai mentionné dans la question liée , mais cela vaut probablement la peine de pointer ici aussi: cela est couvert par dart.dev/tools/non-pomotion-reasons