Home > other >  What is the difference between ?? and =?? in Dart?
What is the difference between ?? and =?? in Dart?

Time:05-02

In the code below to implement the Singleton design pattern, we approach two different ways. One of them creates Singleton but the other creates an object each time we call it. What's the difference between ?? and =?? in the code below written in dart?

class ExampleStateByDefinition extends ExampleStateBase {
  static ExampleStateByDefinition? _instance;

  ExampleStateByDefinition._internal() {
    initialText = 'A new "ExampleStateByDefinition" instance has been created.';
    stateText = initialText;
    print(stateText);
  }

  static ExampleStateByDefinition? getState() {
    return _instance ?? ExampleStateByDefinition._internal();     //here we use ??
  }
}

The above code creates an object each time we call it, so let us look at another variant:

class ExampleStateByDefinition extends ExampleStateBase {
  static ExampleStateByDefinition? _instance;

  ExampleStateByDefinition._internal() {
    initialText = 'A new "ExampleStateByDefinition" instance has been created.';
    stateText = initialText;
    print(stateText);
  }

  static ExampleStateByDefinition? getState() {
    _instance ??= ExampleStateByDefinition._internal();        //Here we use ??=
    return _instance;
  }
}

The above code implements Singleton by definition in Design Patterns: Elements of Reusable Object-Oriented Software

CodePudding user response:

Based on dart tour.

To assign only if the assignment to the variable is null we use ??= operation.

expr1 ?? expr2 if expr1 is not null, return its value; otherwise, evaluates and return the value of expr2.

Cause ?? operation evaluates each time we call the object, it creates a new object.

CodePudding user response:

Both ?? and ??= are null-aware operators.

Difference

The difference between the two operators is that the former only evaluates an expression while the latter also assigns the result of the expression.

This is why your first sample returns a new instance each time since you never assign it to your static variable.

??

Use ?? when you want to evaluate and return an expression IFF another expression resolves to null.

The following expression:

exp ?? otherExp;

Is similar to this expression:

((x) => x == null ? otherExp : x)(exp);

??=

Use ??= when you want to assign a value to an object IFF that object is null. Otherwise, return the object.

The following expression:

obj ??= value;

Is similar to this expression:

((x) => x == null ? obj = value : x)(obj);

See Null-aware operators in Dart for reference.

CodePudding user response:

The ??= operator is a compound assignment operator. Just like target = 1 is equivalent to target = target 1 (but with target only evaluated once, if it's a complicated expression), target ??= expression is equivalent to target = target ?? expression (but with target only evaluated once and the assignment not even happening if target is non-null).

So, yhe difference is that the first code probably doesn't work, the second one does.

The code:

 return _instance ?? ExampleStateByDefinition._internal();

checks whether _instance is non-null, and if so, it returns the value of _instance. If it is null, it evaluates and returns ExampleStateByDefinition._internal(). No-where in that does it assign to _instance. So, _instance is always going to be null, and the code is probably failing to do what it intended to do—caching a value.

The code:

 _instance ??= ExampleStateByDefinition._internal();  
 return _instance;

or its more streamlined version:

 return _instance ??= ExampleStateByDefinition._internal();  

will also check if _instance is null and return its value if it isn't. If _instance is null, it also evaluates ExampleStateByDefinition._internal();, and then it assigns it to _instance, and returns the value.

The next time you come around, _instance will be non-null, and the lazy caching works.

  • Related