In nullsafety.dartpad.dev, wenn ich den folgenden Code schreibe:

void main() {
  String? name = 'Bob';
  print(name.length);
}

Ich erhalte den folgenden Fehler beim Kompilieren:

Ein Ausdruck, dessen Wert 'null' sein kann, muss null geprüft werden, bevor er dereferenziert werden kann

Und der folgende Laufzeitfehler:

Auf die Eigenschaft 'Länge' kann nicht über 'String?' weil es möglicherweise null ist.

Die Typ-Promotion bei Nullprüfungen Dokumentation sagt:

Die Sprache ist auch schlauer darüber, welche Arten von Ausdrücken Werbung verursachen. Ein explizites == null oder != null funktioniert natürlich. Aber explizite Casts mit as, oder Zuweisungen oder dem Postfix-Operator !, den wir bald erhalten werden, verursachen auch Werbung. Das allgemeine Ziel ist, dass die Analyse klug genug sein sollte, wenn der Code dynamisch korrekt ist und es sinnvoll ist, dies statisch herauszufinden.

Frage

Es gibt keine Möglichkeit, dass name im obigen Code null sein könnte. In der Dokumentation heißt es auch, dass Zuweisungen eine Typ-Promotion verursachen sollten. Verstehe ich die Typwerbung falsch oder ist dies ein Fehler in DartPad?

Klärung

Da einige der Antworten Problemumgehungslösungen für die Fehlermeldungen enthalten, sollte ich klarstellen, dass ich nicht versuche, das oben beschriebene Codierungsproblem zu lösen. Ich sage vielmehr, dass ich denke, dass der Code so funktionieren sollte, wie er ist. Aber das tut es nicht. Warum nicht?

7
Suragch 22 Aug. 2020 im 03:26

3 Antworten

Beste Antwort

Diese Antwort ist eine Antwort auf das Kopfgeld, das der ursprünglichen Frage hinzugefügt wurde. Das Kopfgeld lautet:

Bitte erläutern Sie, wie sich String? von String unterscheidet und wie der Typ lautet Promotion funktioniert in Dart.

String? vs String

Der Typ String? kann eine Zeichenfolge oder null enthalten. Hier sind einige Beispiele:

String? string1 = 'Hello world';
String? string2 = 'I ❤️ Dart';
String? string3 = '';
String? string4 = null;

Der Typ String hingegen kann nur Strings enthalten (dh wenn die Nullsicherheit Teil von Dart ist). Es darf nicht null enthalten. Hier sind einige Beispiele:

String string1 = 'Hello world';
String string2 = 'I ❤️ Dart';
String string3 = '';

Wenn Sie Folgendes versuchen:

String string4 = null;

Sie erhalten den Fehler bei der Kompilierung:

A value of type 'Null' can't be assigned to a variable of type 'String'.

Der Typ String kann nicht mehr null sein als ein int wie 3 oder ein bool wie true. Darum geht es bei Null Safety. Wenn Sie eine Variable mit dem Typ String haben, ist garantiert, dass die Variable niemals null sein wird.

Wie Typ Promotion funktioniert

Wenn der Compiler logisch bestimmen kann, dass ein nullbarer Typ (wie String?) niemals null sein wird, konvertiert (oder fördert) er den Typ in sein nicht nullbares Gegenstück (wie String). .

Hier ist ein Beispiel, wo dies wahr ist:

void printNameLength(String? name) {
  if (name == null) {
    return;
  }
  print(name.length);
}

Obwohl der Parameter name nullwertfähig ist, kehrt die Funktion vorzeitig zurück, wenn er tatsächlich null ist. Wenn Sie zu name.length gelangen, weiß der Compiler mit Sicherheit, dass name nicht null sein kann. Der Compiler befördert also den Namen von String? nach String. Der Ausdruck name.length verursacht niemals einen Absturz.

Ein ähnliches Beispiel finden Sie hier:

String? name;
name = 'Bob';
print(name.length);

Obwohl name auch hier nullbar ist, ist das String-Literal 'Bob' offensichtlich nicht null. Dies führt auch dazu, dass name zu einem nicht nullbaren String heraufgestuft wird.

Die ursprüngliche Frage betraf Folgendes:

String? name = 'Bob';
print(name.length);

Es scheint, dass dies auch den Namen zu einem nicht nullbaren String heraufstufen sollte, aber das tat es nicht. Wie @lrn (ein Google-Ingenieur) in der Kommentare Dies ist jedoch ein Fehler. Wenn keine Sicherheit vorliegt, funktioniert dies auch wie im vorherigen Beispiel. Das heißt, name wird zu einem nicht nullbaren String heraufgestuft.

Weiterführende Literatur

2
Suragch 13 Okt. 2020 im 05:37

Da Sie die Variable name als Zeichenfolge deklariert haben, die an einem bestimmten Punkt Ihres Codes null sein kann, müssen Sie bei der Verwendung überprüfen, ob sie null ist, und sie sicher aufrufen. Sie können Ihre Variable name auf zwei Arten sicher verwenden:

1. ANHANG (?) An die Variable

Wenn Sie sicher sind, dass die Variable nicht null ist, können Sie sie verwenden / aufrufen, indem Sie einfach ein ? an sie anhängen.

void main() {
      String? name = 'Bob';
      print(name?.length);
    }

2. ANHANG (!) An die Variable

Das Anhängen von ! an die Variable name löst einen Laufzeitfehler aus, wenn er null ist, und konvertiert ihn andernfalls in einen nicht nullbaren Wert.

void main() {
  String? name = 'Bob';
  print(name!.length);
}

Um den Laufzeitfehler zu vermeiden, wenn die Variable name null ist, müssen Sie zuerst ihre Nullfähigkeit überprüfen und sie dann sicher verwenden.

void main() {
  String? name = 'Bob';
 
  if (name != null) {
     print(name!.length);
  }
}
0
Calleb Developer 22 Aug. 2020 im 01:15

Ich verstehe was du sagst. Probieren Sie es aus.

enter image description here

Damit die Typherabstufung funktioniert, müssen Sie zunächst bestätigen, dass der Wert nicht null ist, wie in der Dokumentation angegeben.

Wie Sie auf dem Bild sehen können, kann Dart die Typ-Promotion durchführen oder verstehen, dass der Name nicht null sein wird, da dies zuvor in der if-Anweisung überprüft wird.

Wenn Sie es jedoch außerhalb der if-Anweisung verwenden, ohne vorher zu prüfen, ob es nicht null ist, weiß dart, dass es jederzeit wieder null zugewiesen werden kann. Aus diesem Grund wird empfohlen, immer zu überprüfen, ob es null ist. Weil jede instatiierte Variable (eine Variable mit einem zugewiesenen Wert) in Zukunft null zugewiesen werden kann.

0
Suragch 22 Aug. 2020 im 01:21