dartudpdart-null-safetyuint8list

dart null safety and typing issues


I'm trying to learn Dart, but I'm having a really hard time wrapping my head around the Null Safety. I have the function below, which I copied straight from the dev example (https://pub.dev/packages/udp) and tweaked for my code just slightly.

void udpConnection(port) async {
    var sender = await UDP.bind(Endpoint.any(port: Port(65000)));
    
    var dataLength = await sender.send('Hello World!'.codeUnits, Endpoint.broadcast(port: Port(port)));
    
    var receiver = await UDP.bind(Endpoint.loopback(port: Port(65002)));
    try {
        receiver.asStream(timeout: Duration(seconds: 20)).listen((datagram) {
            String s = new String.fromCharCodes(datagram.data);
            print(s);
        });
    } catch(e) {
        print(e);
    }
    
    // close the UDP instances and their sockets.
    sender.close();
    receiver.close();
}

But I get the following error:

Error: Property 'data' cannot be accessed on 'Datagram?' because it is potentially null.
 - 'Datagram' is from 'dart:io'.
Try accessing using ?. instead.
                                        String s = new String.fromCharCodes(datagram.data);
                                                                                     ^^^^

However, if I do String s = new String.fromCharCodes(datagram?.data);, I get the following error:

Error: The argument type 'Uint8List?' can't be assigned to the parameter type 'Iterable<int>' because 'Uint8List?' is nullable and 'Iterable<int>' isn't.
 - 'Uint8List' is from 'dart:typed_data'.
 - 'Iterable' is from 'dart:core'.
                                String s = new String.fromCharCodes(datagram?.data);
                                                                    ^

How can I access the data property of the Datagram correctly?


Solution

  • The conditional member access operator (?.) evaluates to null if the left-hand-side is null. The point of it is to avoid generating a null-pointer exception by attempting to access a non-existent member on null.

    Using String.fromCharCodes(datagram?.data) would not magically avoid calling the String.fromCharCodes constructor, and String.fromCharCodes expects a non-null argument.

    You either must give String.fromCharCodes a value that you guarantee is not null or must avoid calling it. Examples:

    // If datagram?.data is null, fall back to using an empty string.
    var s = String.fromCharCodes(datagram?.data ?? '');
    

    or:

    var data = datagram?.data;
    if (data != null) {
      var s = String.fromCharCodes(data);
      ...
    }
    

    I strongly recommend reading Understanding null safety if you haven't already done so.

    Note that ?. and ?? are null-aware operators but aren't really about null-safety. Null-safety is about using the type system to ensure that variables cannot be null when you don't expect them to be.