Dart'daki Güvenlik Açığı nedir (Varsayılan olarak null edilemez)?


Yanıtlar:


49

Sıfırlanamaz (varsayılan olarak)

Null edilemeyen (varsayılan olarak) deneme şu anda nullsafety.dartpad.dev adresinde bulunabilir . Tüm teknik özellikleri burada ve tam yol haritasını burada
okuyabileceğinizi unutmayın .


Varsayılan olarak sıfırlanamaz ne anlama gelir?

void main() {
  String word;
  print(word); // illegal

  word = 'Hello, ';
  print(word); // legal
}

Yukarıda görebileceğiniz gibi, varsayılan olarak null değerinin geçersiz olması bir değişkenin normal olarak bildirilen her değişkenin yapılamayacağı anlamına gelir null. Sonuç olarak, değişkene atanmadan önce erişen herhangi bir işlem geçersizdir.
Ayrıca, nullboş olmayan bir değişkene atamaya da izin verilmez:

void main() {
  String word;

  word = null; // forbidden
  world = 'World!'; // allowed
}

Bu bana nasıl yardımcı oluyor?

Bir değişken geçersiz kılınamazsa , değişkenin hiçbir zamannull . Bu nedenle, önceden önceden kontrol etmenize gerek yoktur.

int number = 4;

void main() {
  if (number == null) return; // redundant

  int sum = number + 2; // allowed because number is also non-nullable
}

Hatırlamak

Sınıflardaki örnek alanları, boş değerli değilse başlatılmalıdır :

class Foo {
  String word; // forbidden

  String sentence = 'Hello, World!'; // allowed
}

Görmek lateBu davranışı değiştirmek için aşağıya .

Null olabilecek türler (? )

Değişken türüne soru işareti ekleyerek null olabilecek türleri kullanabilirsiniz ?:

class Foo {
  String word; // forbidden

  String? sentence; // allowed
}

Bir null o kullanılmadan önce değişken başlatılması için gerekli değildir. nullVarsayılan olarak başlatılır :

void main() {
  String? word;

  print(word); // prints null
}

!

Ekleme !herhangi değişkene ebir atacağım çalışma zamanı hatası varsa enull ve aksi bir dönüştürmek NULL olmayan değere v.

void main() {
  int? e = 5;
  int v = e!; // v is non-nullable; would throw an error if e were null

  String? word;
  print(word!); // throws runtime error if word is null

  print(null!); // throws runtime error
}

late

Anahtar kelime daha sonra başlatılacaklate olan değişkenleri işaretlemek için kullanılabilir , yani bildirildiklerinde değil, erişildiklerinde. Bu ayrıca, daha sonra başlatılacak nullable olmayan örnek alanlarımız olabileceği anlamına gelir :

class ExampleState extends State {
  late String word; // non-nullable

  @override
  void initState() {
    super.initState();

    // print(word) here would throw a runtime error
    word = 'Hello';
  }
}

wordBaşlatılmadan önce erişmek bir çalışma zamanı hatası verir.

late final

Son değişkenler artık geç olarak da işaretlenebilir:

late final int x = heavyComputation();

Burada heavyComputationsadece bir kez xerişilir çağrılır . Ayrıca, late finalyalnızca latedeğişkene sahip olanla aynı olan bir başlatıcısı olmayan bir de bildirebilirsiniz, ancak yalnızca bir kez atanabilir.

late final int x;
// w/e
x = 5; // allowed
x = 6; // forbidden

Başlatıcı içeren tüm üst düzey veya statik değişkenlerin şimdi lateolursa olsun değerlendirileceğini unutmayın final.

required

Önceden bir ek açıklama ( @required), şimdi değiştirici olarak yerleşik. Adlandırılmış herhangi bir parametrenin (işlevler veya sınıflar için) olarak işaretlenmesine izin verir required, bu da onları boş bırakılamaz yapar:

void allowed({required String word}) => null;

Bu ayrıca, bir parametrenin nullable olmaması gerektiğinde, requiredvarsayılan olarak işaretlenmesi veya varsayılan bir değere sahip olması gerektiği anlamına gelir :

void allowed({String word = 'World'}) => null;

void forbidden({int x}) // compile-time error because x can be null (unassigned)
    =>
    null;

Adlandırılmış diğer tüm parametrelerin boş değerli olması gerekir :

void baz({int? x}) => null;

?[]

?[]Dizin operatörü için null farkında operatör eklendi []:

void main() {
  List<int>? list = [1, 2, 3];

  int? x = list?[0]; // 1
}

Sözdizimi kararı ile ilgili bu makaleye de bakın .

?..

Art arda sıralı operatörün artık yeni bir sıfır bilinçli operatörü var: ?.. .

Aşağıdaki kaskat işlemlerinin yalnızca alıcı boş değilse yürütülmesine neden olur . Bu nedenle, ?..kaskad dizisindeki ilk kaskad operatörü olmalıdır:

void main() {
  Path? path;

  // Will not do anything if path is null.
  path
    ?..moveTo(3, 4)
    ..lineTo(4, 3);

  // This is a noop.
  (null as List)
    ?..add(4)
    ..add(2)
    ..add(0);
}

Never

Karışıklığı önlemek için: Bu, geliştiricilerin endişelenmesi gereken bir şey değildir. Bütünlük uğruna bahsetmek istiyorum.

NeverÖnceden var olan benzeri bir tür olacak Null( değilnull tanımlanmıştır) dart:core. Bu sınıfların her ikisi de genişletilemez, uygulanamaz veya karıştırılamaz, bu nedenle kullanılması amaçlanmamıştır.

Esasen, Neverhiçbir tipe izin verilmediği ve Neverkendisinin somutlaştırılamadığı anlamına gelir .
Hiçbir şey ama Neverbir de List<Never>o anlama geldiğini listenin tatmin genel tür kısıtlaması olmak zorunda boş . List<Null>ancak şunları içerebilir null:

// Only valid state: []
final neverList = <Never>[
  // Any value but Never here will be an error.
  5, // error
  null, // error

  Never, // not a value (compile-time error)
];

// Can contain null: [null]
final nullList = <Null>[
  // Any value but Null will be an error.
  5, // error
  null, // allowed

  Never, // not a value (compile-time error)
  Null, // not a value (compile-time error)
];

Örnek: derleyici boşList<Never> için çıkarım yapar . endişelendiğim kadarıyla programcılar tarafından kullanılmaması gerekiyordu. const List<T>
Never


5
NeverKullanılabilecek bazı senaryolar verebilir misiniz ?
Ramses Aldama

2
Aslında null-farkında dizin operatörü için "?. []" Yerine "? []" Kullanmaya karar verdik. İkincisi dilbilgisi açısından biraz daha karmaşıktır, ancak kullanıcıların istediği budur.
munificent

@RamsesAldama Bir şey ekledim. Bağlantı verdiğim şartnamede daha fazla bahsediliyor.
creativecreatorormaybenot

@munificent Spesifikasyon ve deney hala modası geçmiş; işaret ettiğin için teşekkürler.
creativecreatorormaybenot

1
late finalBir üye veya örnek değişkeni üzerinde yalnızca çalışma zamanında kontrol edildiğine dikkat edilmelidir . Durma problemi nedeniyle bunu geliştirme zamanında veya derleme zamanında kontrol etmek mümkün değildir. Yani IDE yardımı almayacaksınız.
Graham
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.