Dart 3.10 is taking off with dot shorthands, stable build hooks, nuanced deprecation annotations, and more!Learn more
Dart supports the operators shown in the following table. The table shows Dart's operator associativity andoperator precedence from highest to lowest, which are anapproximation of Dart's operator relationships. You can implement many of theseoperators as class members.
| Description | Operator | Associativity |
|---|---|---|
| unary postfix | expr++ expr-- () [] ?[] . ?. ! | None |
| unary prefix | -expr !expr ~expr ++expr --expr awaitexpr | None |
| multiplicative | * / % ~/ | Left |
| additive | + - | Left |
| shift | << >> >>> | Left |
| bitwise AND | & | Left |
| bitwise XOR | ^ | Left |
| bitwise OR | | | Left |
| relational and type test | >= > <= < as is is! | None |
| equality | == != | None |
| logical AND | && | Left |
| logical OR | || | Left |
| if-null | ?? | Left |
| conditional | expr1 ? expr2 : expr3 | Right |
| cascade | .. ?.. | Left |
| assignment | = *= /= += -= &= ^= etc. | Right |
| spread (See note) | ... ...? | None |
The previous table should only be used as a helpful guide. The notion of operator precedence and associativity is an approximation of the truth found in the language grammar. You can find the authoritative behavior of Dart's operator relationships in the grammar defined in theDart language specification.
When you use operators, you create expressions. Here are some examples of operator expressions:
a++a+ba=ba==bc?a:baisTOperator precedence example
# In theoperator table, each operator has higher precedence than the operators in the rows that follow it. For example, the multiplicative operator% has higher precedence than (and thus executes before) the equality operator==, which has higher precedence than the logical AND operator&&. That precedence means that the following two lines of code execute the same way:
// Parentheses improve readability.if((n%i==0)&&(d%i==0)){// ...}// Harder to read, but equivalent.if(n%i==0&&d%i==0){// ...} For operators that take two operands, the leftmost operand determines which method is used. For example, if you have aVector object and aPoint object, thenaVector + aPoint usesVector addition (+).
Arithmetic operators
#Dart supports the usual arithmetic operators, as shown in the following table.
| Operator | Meaning |
|---|---|
+ | Add |
- | Subtract |
-expr | Unary minus, also known as negation (reverse the sign of the expression) |
* | Multiply |
/ | Divide |
~/ | Divide, returning an integer result |
% | Get the remainder of an integer division (modulo) |
Example:
assert(2+3==5);assert(2-3==-1);assert(2*3==6);assert(5/2==2.5);// Result is a doubleassert(5~/2==2);// Result is an intassert(5%2==1);// Remainderassert('5/2 =${5 ~/ 2} r${5 % 2}'=='5/2 = 2 r 1');Dart also supports both prefix and postfix increment and decrement operators.
| Operator | Meaning |
|---|---|
++var | var = var+ 1 (expression value isvar + 1 ) |
var++ | var = var+ 1 (expression value isvar ) |
--var | var = var- 1 (expression value isvar - 1 ) |
var-- | var = var- 1 (expression value isvar ) |
Example:
inta;intb;a=0;b=++a;// Increment a before b gets its value.assert(a==b);// 1 == 1a=0;b=a++;// Increment a after b gets its value.assert(a!=b);// 1 != 0a=0;b=--a;// Decrement a before b gets its value.assert(a==b);// -1 == -1a=0;b=a--;// Decrement a after b gets its value.assert(a!=b);// -1 != 0Equality and relational operators
#The following table lists the meanings of equality and relational operators.
| Operator | Meaning |
|---|---|
== | Equal; see discussion below |
!= | Not equal |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
To test whether two objects x and y represent the same thing, use the== operator. (In the rare case where you need to know whether two objects are the exact same object, use theidentical() function instead.) Here's how the== operator works:
Ifx ory is null, return true if both are null, and false if only one is null.
Return the result of invoking the
==method onx with the argumenty. (That's right, operators such as==are methods that are invoked on their first operand. For details, seeOperators.)
Here's an example of using each of the equality and relational operators:
assert(2==2);assert(2!=3);assert(3>2);assert(2<3);assert(3>=3);assert(2<=3);Type test operators
# Theas,is, andis! operators are handy for checking types at runtime.
| Operator | Meaning |
|---|---|
as | Typecast (also used to specifylibrary prefixes ) |
is | True if the object has the specified type |
is! | True if the object doesn't have the specified type |
The result ofobj is T is true ifobj implements the interface specified byT. For example,obj is Object? is always true.
Use theas operator to cast an object to a particular type if and only if you are sure that the object is of that type. Example:
(employeeasPerson).firstName='Bob'; If you aren't sure that the object is of typeT, then useis T to check the type before using the object.
if(employeeisPerson){// Type checkemployee.firstName='Bob';} The code isn't equivalent. Ifemployee is null or not aPerson, the first example throws an exception; the second does nothing.
Assignment operators
# As you've already seen, you can assign values using the= operator. To assign only if the assigned-to variable is null, use the??= operator.
// Assign value to aa=value;// Assign value to b if b is null; otherwise, b stays the sameb??=value; Compound assignment operators such as+= combine an operation with an assignment.
= | *= | %= | >>>= | ^= |
+= | /= | <<= | &= | |= |
-= | ~/= | >>= |
Here's how compound assignment operators work:
| Compound assignment | Equivalent expression | |
|---|---|---|
| For an operatorop: | aop= b | a = aopb |
| Example: | a += b | a = a + b |
The following example uses assignment and compound assignment operators:
vara=2;// Assign using =a*=3;// Assign and multiply: a = a * 3assert(a==6);Logical operators
#You can invert or combine boolean expressions using the logical operators.
| Operator | Meaning |
|---|---|
!expr | inverts the following expression (changes false to true, and vice versa) |
|| | logical OR |
&& | logical AND |
Here's an example of using the logical operators:
if(!done&&(col==0||col==3)){// ...Do something...}Bitwise and shift operators
#You can manipulate the individual bits of numbers in Dart. Usually, you'd use these bitwise and shift operators with integers.
| Operator | Meaning |
|---|---|
& | AND |
| | OR |
^ | XOR |
~expr | Unary bitwise complement (0s become 1s; 1s become 0s) |
<< | Shift left |
>> | Shift right |
>>> | Unsigned shift right |
The behavior of bitwise operations with large or negative operands might differ between platforms. To learn more, check outBitwise operations platform differences.
Here's an example of using bitwise and shift operators:
finalvalue=0x22;finalbitmask=0x0f;assert((value&bitmask)==0x02);// ANDassert((value&~bitmask)==0x20);// AND NOTassert((value|bitmask)==0x2f);// ORassert((value^bitmask)==0x2d);// XORassert((value<<4)==0x220);// Shift leftassert((value>>4)==0x02);// Shift right// Shift right example that results in different behavior on web// because the operand value changes when masked to 32 bits:assert((-value>>4)==-0x03);assert((value>>>4)==0x02);// Unsigned shift rightassert((-value>>>4)>0);// Unsigned shift right The>>> operator (known astriple-shift orunsigned shift) requires alanguage version of at least 2.14.
Conditional expressions
#Dart has two operators that let you concisely evaluate expressions that might otherwise requireif-else statements:
condition?expr1:expr2Ifcondition is true, evaluatesexpr1 (and returns its value); otherwise, evaluates and returns the value ofexpr2.
expr1??expr2Ifexpr1 is non-null, returns its value; otherwise, evaluates and returns the value ofexpr2.
When you need to assign a value based on a boolean expression, consider using the conditional operator? and:.
varvisibility=isPublic?'public':'private'; If the boolean expression tests for null, consider using the if-null operator?? (also known as the null-coalescing operator).
StringplayerName(String?name)=>name??'Guest';The previous example could have been written at least two other ways, but not as succinctly:
// Slightly longer version uses ?: operator.StringplayerName(String?name)=>name!=null?name:'Guest';// Very long version uses if-else statement.StringplayerName(String?name){if(name!=null){returnname;}else{return'Guest';}}Cascade notation
# Cascades (..,?..) allow you to make a sequence of operations on the same object. In addition to accessing instance members, you can also call instance methods on that same object. This often saves you the step of creating a temporary variable and allows you to write more fluid code.
Consider the following code:
varpaint=Paint()..color=Colors.black..strokeCap=StrokeCap.round..strokeWidth=5.0; The constructor,Paint(), returns aPaint object. The code that follows the cascade notation operates on this object, ignoring any values that might be returned.
The previous example is equivalent to this code:
varpaint=Paint();paint.color=Colors.black;paint.strokeCap=StrokeCap.round;paint.strokeWidth=5.0; If the object that the cascade operates on can be null, then use anull-shorting cascade (?..) for the first operation. Starting with?.. guarantees that none of the cascade operations are attempted on that null object.
document.querySelector('#confirm')// Get an object.?..textContent='Confirm'// Use its members...classList.add('important')..onClick.listen((e)=>window.alert('Confirmed!'))..scrollIntoView();The previous code is equivalent to the following:
finalbutton=document.querySelector('#confirm');button?.textContent='Confirm';button?.classList.add('important');button?.onClick.listen((e)=>window.alert('Confirmed!'));button?.scrollIntoView();You can also nest cascades. For example:
finaladdressBook=(AddressBookBuilder()..name='jenny'..email='jenny@example.com'..phone=(PhoneNumberBuilder()..number='415-555-0100'..label='home').build()).build();Be careful to construct your cascade on a function that returns an actual object. For example, the following code fails:
varsb=StringBuffer();sb.write('foo')..write('bar');// Error: method 'write' isn't defined for 'void'. Thesb.write() call returns void, and you can't construct a cascade onvoid.
Strictly speaking, the "double dot" notation for cascades isn't an operator. It's just part of the Dart syntax.
Spread operators
#Spread operators evaluate an expression that yields a collection, unpacks the resulting values, and inserts them into another collection.
The spread operator isn't actually an operator expression. The.../...? syntax is part of the collection literal itself. So, you can learn more about spread operators on theCollections page.
Because it isn't an operator, the syntax doesn't have any "operator precedence". Effectively, it has the lowest "precedence" — any kind of expression is valid as the spread target, such as:
[...a+b]Other operators
#You've seen most of the remaining operators in other examples:
| Operator | Name | Meaning |
|---|---|---|
() | Function application | Represents a function call |
[] | Subscript access | Represents a call to the overridable[] operator; example:fooList[1] passes the int1 tofooList to access the element at index1 |
?[] | Conditional subscript access | Like[] , but the leftmost operand can be null; example:fooList?[1] passes the int1 tofooList to access the element at index1 unlessfooList is null (in which case the expression evaluates to null) |
. | Member access | Refers to a property of an expression; example:foo.bar selects propertybar from expressionfoo |
?. | Conditional member access | Like. , but the leftmost operand can be null; example:foo?.bar selects propertybar from expressionfoo unlessfoo is null (in which case the value offoo?.bar is null) |
! | Not-null assertion operator | Casts an expression to its underlying non-nullable type, throwing a runtime exception if the cast fails; example:foo!.bar assertsfoo is non-null and selects the propertybar , unlessfoo is null (in which case a runtime exception is thrown) |
For more information about the.,?., and.. operators, seeClasses.
Unless stated otherwise, the documentation on this site reflects Dart 3.10.0. Page last updated on 2025-10-15.View source orreport an issue.