This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Assignment operators (C# reference)

  • 11 contributors

The assignment operator = assigns the value of its right-hand operand to a variable, a property , or an indexer element given by its left-hand operand. The result of an assignment expression is the value assigned to the left-hand operand. The type of the right-hand operand must be the same as the type of the left-hand operand or implicitly convertible to it.

The assignment operator = is right-associative, that is, an expression of the form

is evaluated as

The following example demonstrates the usage of the assignment operator with a local variable, a property, and an indexer element as its left-hand operand:

The left-hand operand of an assignment receives the value of the right-hand operand. When the operands are of value types , assignment copies the contents of the right-hand operand. When the operands are of reference types , assignment copies the reference to the object.

This is called value assignment : the value is assigned.

ref assignment

Ref assignment = ref makes its left-hand operand an alias to the right-hand operand, as the following example demonstrates:

In the preceding example, the local reference variable arrayElement is initialized as an alias to the first array element. Then, it's ref reassigned to refer to the last array element. As it's an alias, when you update its value with an ordinary assignment operator = , the corresponding array element is also updated.

The left-hand operand of ref assignment can be a local reference variable , a ref field , and a ref , out , or in method parameter. Both operands must be of the same type.

Compound assignment

For a binary operator op , a compound assignment expression of the form

is equivalent to

except that x is only evaluated once.

Compound assignment is supported by arithmetic , Boolean logical , and bitwise logical and shift operators.

Null-coalescing assignment

You can use the null-coalescing assignment operator ??= to assign the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates to null . For more information, see the ?? and ??= operators article.

Operator overloadability

A user-defined type can't overload the assignment operator. However, a user-defined type can define an implicit conversion to another type. That way, the value of a user-defined type can be assigned to a variable, a property, or an indexer element of another type. For more information, see User-defined conversion operators .

A user-defined type can't explicitly overload a compound assignment operator. However, if a user-defined type overloads a binary operator op , the op= operator, if it exists, is also implicitly overloaded.

C# language specification

For more information, see the Assignment operators section of the C# language specification .

  • C# operators and expressions
  • ref keyword
  • Use compound assignment (style rules IDE0054 and IDE0074)

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

DEV Community

DEV Community

Matheus Gomes 👨‍💻

Posted on Jan 5, 2020

Coalescing operator and Compound assignment operator in C#

Hello! Today i want to ask you this: Have you ever used a Null Coalescing operator or even a Compound assignment operator in C# ?

Until today i had never heard about this things, so i want to share with you what i learned about and how it can be applied to your code.

The problem

Let's say you want to give a given variable the value of null.

Now, if we want to print the value on the screen it will accuse the following error:

Let's see how to get around this...

The old way 👎

The old and 'commom way' to check this is using if else operators like this:

We see that in this case we cannot place a default value to x and y operators. So we display on screen when it is null.

The Null Coalescing operator way 👌

First, a null coalescing operator (??) is used to define a default value for nullable value types or reference types. It returns the left-hand operand if the operand is not null, otherwise, it returns the right operand.

So it's mainly used to simplify checking for null values and also assign a default value to a variable when the value is null.

Using our example:

This way i can make a default value on x and y when one of them is null. And so, we can print on screen!

But can it be better?

The Compound assignment operator way 😎

The Compound assignment operator (??=) was introduced on C# 8.0 and has made our job easier. It simply reduces what we have to write and has the same result.

Instead of writing double x = x ?? 0.0; We can just write double x ??= 0.0;

Simple, right?

Hope you enjoyed this post, it's simple but it's something worth sharing for me.

Thanks for your time!😊

Links: https://dzone.com/articles/nullable-types-and-null-coalescing-operator-in-c

https://dev.to/mpetrinidev/the-null-coalescing-operator-in-c-8-0-4ib4

https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/operators/null-coalescing-operator

Top comments (3)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

wakeupmh profile image

  • Email [email protected]
  • Location São José dos Campos
  • Work Cloud Engineer | AWS Community Builder
  • Joined May 21, 2019

saint4eva profile image

  • Joined Dec 16, 2017

Good article. Thank you.

arthurbarbero profile image

  • Location Brazil
  • Work Intern at Agrotools
  • Joined Oct 22, 2019

Awesome Dude, simple but unknown by most programmers

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

adrianbailador profile image

Implementing Messaging in .NET: A Comprehensive Guide

Adrián Bailador - Apr 21

botticellibots profile image

Making a Telegram bot with BotticelliBots

BotticelliBots - Apr 10

tkarropoulos profile image

Understanding IQueryable in C#

Theodore Karropoulos - Apr 20

jcbhmr profile image

🏎 Use task.go for your Go project scripts

Jacob Hummer - Apr 19

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

C# 8 - Null coalescing/compound assignment

There are a lot of cool new features in C# 8 and one of my favorites is the new Null coalescing assignment operator.

Stefán Jökull Sigurðarson

Stefán Jökull Sigurðarson

Hi friends.

There are a lot of cool new features in C# 8 and one of my favorites is the new Null coalescing assignment (or compound assignment, whichever you prefer) operator. If you have ever written code like this:

You can simplify this code A LOT!

That is the new ??= operator in action, which takes care of doing the null check and assignment for you in one sweet syntactic sugar-rush! I also find it more readable, but some people might disagree, and that fine. Just pick whatever you prefer :)

And the best part is that it actually compiles down to the same efficient code! Just take a look at this sharplab.io sample to see what I mean.

You might have solved this with a Lazy<string> or by using something like _someValue = _someValue ?? InitializeMyValue(); as well but that's still more code to write than the new operator and less efficient as well. The Lazy<T> approach has some overhead and the null-coalescing operator + assignment has the added inefficiency of always making the variable assignment even if there is no need to (you can take a closer look at the ASM part of the SharpLab example above) but there it is for reference:

Hope this helps! :)

Sign up for more like this.

Operators and Control Flow

I n this chapter , you learn about operators, control flow statements, and the C# preprocessor. Operators provide syntax for performing different calculations or actions appropriate for the operands within the calculation. Control flow statements provide the means for conditional logic within a program or looping over a section of code multiple times. After introducing the if control flow statement, the chapter looks at the concept of Boolean expressions, which are embedded within many control flow statements. Included is mention of how integers cannot be converted (even explicitly) to bool and the advantages of this restriction. The chapter ends with a discussion of the C# preprocessor directives.

Now that you have been introduced to the predefined data types (refer to Chapter 2), you can begin to learn how to use these data types in combination with operators to perform calculations. For example, you can make calculations on variables that you have declared.

Operators are used to perform mathematical or logical operations on values (or variables) called operands to produce a new value, called the result . For example, in Listing 4.1 the subtraction operator, - , is used to subtract two operands, the numbers 4 and 2 . The result of the subtraction is stored in the variable difference .

There are three operator categories—unary, binary, and ternary—corresponding to the number of operands (one, two, and three, respectively). Furthermore, while some operators are represented with symbols like + , - , ?. , and ?? , other operators take the form of keywords, like default and is . This section covers some of the most basic unary and binary operators. The ternary operators appear later in the chapter.

Sometimes you may want to change the sign of a numeric value. In these cases, the unary minus operator ( - ) comes in handy. For example, Listing 4.2 changes the total current world debt to a negative value to indicate that it is an amount owed.

Using the minus operator is equivalent to subtracting the operand from zero.

The unary plus operator ( + ) rarely 1 has any effect on a value. It is a superfluous addition to the C# language and was included for the sake of symmetry.

Binary operators require two operands. C# uses infix notation for binary operators: The operator appears between the left and right operands. The result of every binary operator other than assignment must be used somehow—for example, by using it as an operand in another expression such as an assignment.

In contrast to the rule mentioned previously, C++ allows a single binary expression to form the entirety of a statement, such as 4+5; , and compile. In C#, only assignment, call, increment, decrement, await, and object creation expressions are allowed to be the entirety of a statement.

The subtraction example in Listing 4.3 with Output 4.1 illustrates the use of a binary operator—more specifically, an arithmetic binary operator. The operands appear on each side of the arithmetic operator, and then the calculated value is assigned. The other arithmetic binary operators are addition ( + ), division ( / ), multiplication ( * ), and remainder ( % [sometimes called the mod operator]).

In the highlighted assignment statements, the division and remainder operations are executed before the assignments. The order in which operators are executed is determined by their precedence and associativity . The precedence for the operators used so far is as follows:

Therefore, you can assume that the statement behaves as expected, with the division and remainder operators executing before the assignment.

If you forget to assign the result of one of these binary operators, you will receive the compile error shown in Output 4.2 .

When an expression contains multiple operators, it can be unclear precisely what the operands of each operator are. For example, in the expression x+y*z , clearly the expression x is an operand of the addition, and z is an operand of the multiplication. But is y an operand of the addition or the multiplication?

Parentheses allow you to unambiguously associate an operand with its operator. If you wish y to be a summand, you can write the expression as (x+y)*z ; if you want it to be a multiplicand, you can write x+(y*z) .

However, C# does not require you to parenthesize every expression containing more than one operator; instead, the compiler can use associativity and precedence to figure out from the context which parentheses you have omitted. Associativity determines how similar operators are parenthesized; precedence determines how dissimilar operators are parenthesized.

A binary operator may be left-associative or right-associative , depending on whether the expression “in the middle” belongs to the operator on the left or the right. For example, a-b-c is assumed to mean (a-b)-c , and not a-(b-c) ; subtraction is therefore said to be left-associative. Most operators in C# are left-associative; the assignment operators are right-associative.

When the operators are dissimilar, the precedence for those operators is used to determine the side to which the operand in the middle belongs. For example, multiplication has higher precedence than addition, so the expression x+y*z is evaluated as x+(y*z) rather than (x+y)*z .

It is often good practice to use parentheses to make the code more readable, even when the use of parentheses does not change the meaning of the expression. For example, when performing a Celsius-to-Fahrenheit temperature conversion, (c*9.0/5.0)+32.0 is easier to read than c*9.0/5.0+32.0 , even though the parentheses are completely unnecessary.

Clearly, operators of higher precedence must execute before adjoining operators of lower precedence: in x+y*z , the multiplication must be executed before the addition because the result of the multiplication is the right-hand operand of the addition. However, it is important to realize that precedence and associativity affect only the order in which the operators themselves are executed; they do not in any way affect the order in which the operands are evaluated.

Operands are always evaluated from left to right in C#. In an expression with three method calls, such as A()+B()*C() , first A() is evaluated, then B() , then C() ; then the multiplication operator determines the product; and finally the addition operator determines the sum. Just because C() is involved in a multiplication and A() is involved in a lower-precedence addition, that does not imply that method invocation C() happens before method invocation A() .

In contrast to the rule mentioned here, the C++ specification allows an implementation broad latitude to decide the evaluation order of operands. When given an expression such as A()+B()*C() , a C++ compiler can choose to evaluate the function calls in any order, as long as the product is one of the summands. For example, a legal compiler could evaluate B() , then A() , then C() ; then the product; and finally the sum.

Operators can also work with non-numeric operands. For example, it is possible to use the addition operator to concatenate two or more strings, as shown in Listing 4.4 with Output 4.3 .

Because sentence structure varies among languages in different cultures, developers should be careful not to use the addition operator with strings that possibly will require localization. Similarly, although we can embed expressions within a string using string interpolation, localization to other languages still requires moving the string to a resource file, neutralizing the string interpolation. For this reason, you should use the addition operator sparingly, favoring composite formatting when localization is a possibility.

When introducing the char type in Chapter 2, we mentioned that even though it stores characters and not numbers, the char type is an integral type ( integral means it is based on an integer). It can participate in arithmetic operations with other integer types. However, interpretation of the value of the char type is not based on the character stored within it but rather on its underlying value. The digit 3 , for example, is represented by the Unicode value 0x33 (hexadecimal), which in base 10 is 51 . The digit 4 is represented by the Unicode value 0x34 , or 52 in base 10. Adding 3 and 4 in Listing 4.5 results in a hexadecimal value of 0x67 , or 103 in base 10, which is the Unicode value for the letter g , as shown in Output 4.4 .

You can use this trait of character types to determine how far two characters are from each other. For example, the letter f is three characters away from the letter c . You can determine this value by subtracting the letter c from the letter f , as Listing 4.6 with Output 4.5 demonstrates.

The binary floating-point types, float and double , have some special characteristics, such as the way they manage precision. This section looks at some specific examples, as well as some unique floating-point type characteristics.

A float , with seven decimal digits of precision, can hold the value 1,234,567 and the value 0.1234567. However, if you add these two float s together, the result will be rounded to 1,234,567, because the exact result requires more precision than the seven significant digits that a float can hold. The error introduced by rounding off to seven digits can become large compared to the value computed, especially with repeated calculations. (See also “Advanced Topic: Unexpected Inequality with Floating-Point Types” later in this section.)

Internally, the binary floating-point types store a binary fraction, not a decimal fraction. Consequently, “representation error” inaccuracies can occur with a simple assignment, such as double number = 140.6F . The exact value of 140.6 is the fraction 703/5, but the denominator of that fraction is not a power of 2, so a binary floating-point number cannot represent it exactly. Instead, the value represented is the closest fraction with a power of 2 in the denominator that fits into the 32 bits of a float .

Since the double can hold a more accurate value than the float can store, the C# compiler actually evaluates this expression to double number = 140.600006103516 because 140.600006103516 is the closest binary fraction to 140.6 as a float . This fraction is slightly larger than 140.6 when represented as a double .

Because floating-point numbers can be unexpectedly rounded off to non-decimal fractions, comparing floating-point values for equality can be quite confusing. Consider Listing 4.7 with Output 4.6 .

The Assert() methods alert the developer whenever arguments evaluate to false . However, of all the Assert() calls in this code listing, only half have arguments that evaluate to true . Despite the apparent equality of the values in the code listing, they are not actually equivalent due to the inaccuracies associated with float values.

You should be aware of some additional unique floating-point characteristics as well. For instance, you would expect that dividing an integer by zero would result in an error—and it does with data types such as int and decimal . The float and double types, however, allow for certain special values. Consider Listing 4.8 , and its resultant output, Output 4.7 .

In mathematics, certain mathematical operations are undefined, including dividing zero by itself. In C#, the result of dividing the float zero by zero results in a special Not a Number (NaN) value; all attempts to print the output of such a number will result in NaN . Similarly, taking the square root of a negative number with System.Math.Sqrt(-1) will result in NaN .

A floating-point number could overflow its bounds as well. For example, the upper bound of the float type is approximately 3.4 × 10 38 . Should the number overflow that bound, the result would be stored as positive infinity , and the output of printing the number would be Infinity . Similarly, the lower bound of a float type is −3.4 × 10 38 , and computing a value below that bound would result in negative infinity , which would be represented by the string -Infinity . Listing 4.9 produces negative and positive infinity, respectively, and Output 4.8 shows the results.

Further examination of the floating-point number reveals that it can contain a value very close to zero without actually containing zero. If the value exceeds the lower threshold for the float or double type, the value of the number can be represented as negative zero or positive zero , depending on whether the number is negative or positive, and is represented in output as -0 or 0 .

Chapter 1 discussed the simple assignment operator, which places the value of the right-hand side of the operator into the variable on the left-hand side. Compound mathematical assignment operators combine common binary operator calculations with the assignment operator. For example, consider Listing 4.10 .

In this assignment, first you calculate the value of x + 2 , and then you assign the calculated value back to x . Since this type of operation is performed relatively frequently, an assignment operator exists to handle both the calculation and the assignment with one operator. The += operator increments the variable on the left-hand side of the operator with the value on the right-hand side of the operator, as shown in Listing 4.11 .

This code, therefore, is equivalent to Listing 4.10 .

Numerous other compound assignment operators exist to provide similar functionality. You can also use the assignment operator with subtraction, multiplication, division, and remainder operators (as demonstrated in Listing 4.12 ).

C# includes special unary operators for incrementing and decrementing counters. The increment operator , ++ , increments a variable by one each time it is used. In other words, all of the code lines shown in Listing 4.13 are equivalent.

Similarly, you can decrement a variable by 1 using the decrement operator , -- . Therefore, all the code lines shown in Listing 4.14 are also equivalent.

The increment and decrement operators are especially prevalent in loops, such as the while loop described later in the chapter. For example, Listing 4.15 with Output 4.9 uses the decrement operator to iterate backward through each letter in the alphabet.

Listing 4.15 uses the increment and decrement operators to control how many times a particular operation is performed. In this example, notice that the decrement operator acts on a character ( char ) data type. You can use increment and decrement operators on various data types given some meaning is programmed to the concept of the “next” or “previous” value for that data type. See the section “ Operator Overloading ” in Chapter 10.

We saw that the assignment operator first computes the value and then performs the assignment. The result of the assignment operator is the value that was assigned. The increment and decrement operators are similar: They compute the value, perform the assignment, and return a value. It is therefore possible to use the assignment operator with the increment or decrement operator, though doing so carelessly can be extremely confusing. See Listing 4.16 and Output 4.10 for an example.

You might be surprised that result was assigned the value that was count before count was incremented. Where you place the increment or decrement operator determines whether the assigned value should be the value of the operand before or after the calculation. If you want the value of result to be the value assigned to count , you need to place the operator before the variable being incremented, as shown in Listing 4.17 with Output 4.11 .

In this example, the increment operator appears before the operand, so the result of the expression is the value assigned to the variable after the increment. If count is 123 , ++count assigns 124 to count and produces the result 124 . By contrast, the postfix increment operator count++ assigns 124 to count and produces the value that count held before the increment: 123 . Regardless of whether the operator is postfix or prefix, the variable count is incremented before the value is produced; the only difference is which value is produced. The difference between prefix and postfix behavior is illustrated in Listing 4.18 . The resultant output is shown in Output 4.12 .

As Listing 4.18 demonstrates, where the increment and decrement operators appear relative to the operand can affect the result produced by the expression. The result of the prefix operators is the value that the variable had before incrementing or decrementing. The result of the postfix operators is the value that the variable had after incrementing or decrementing. Use caution when embedding these operators in the middle of a statement. When in doubt as to what will happen, use these operators independently, placing them within their own statements. This way, the code is also more readable and there is no mistaking the intention.

Earlier we discussed how the operands in an expression can be evaluated in any order in C++, whereas they are always evaluated from left to right in C#. Similarly, in C++ an implementation may legally perform the side effects of increments and decrements in any order. For example, in C++ a call of the form M(x++, x++) , where x begins as 1 , can legally call either M(1,2) or M(2,1) at the whim of the compiler. In contrast, C# always calls M(1,2) because C# makes two guarantees: (1) The arguments to a call are always computed from left to right, and (2) the assignment of the incremented value to the variable always happens before the value of the expression is used. C++ makes neither guarantee.

Despite the brevity of the increment and decrement operators, these operators are not atomic. A thread context switch can occur during the execution of the operator and can cause a race condition. You could use a lock statement to prevent the race condition. However, for simple increments and decrements, a less expensive alternative is to use the thread-safe Increment() and Decrement() methods from the System.Threading.Interlocked class. These methods rely on processor functions for performing fast, thread-safe increments and decrements. See Chapter 19 for more details.

Chapter 3 discussed literal values, or values embedded directly into the code. It is possible to combine multiple literal values in a constant expression using operators. By definition, a constant expression is one that the C# compiler can evaluate at compile time (instead of evaluating it when the program runs) because it is composed entirely of constant operands. Constant expressions can then be used to initialize constant locals, which allow you to give a name to a constant value (similar to the way local variables allow you to give a name to a storage location). For example, the computation of the number of seconds in a day can be a constant expression that is then used in other expressions by name.

The const keyword in Listing 4.19 declares two constant locals: secondsPerDay and secondsPerWeek . Since a constant local is, by definition, the opposite of a variable — constant means “not able to vary”—any attempt to modify the value later in the code would result in a compile-time error.

In Listing 4.19 , 60 * 60 * 34 and secondsPerDay * 7 are both constant expressions. Note that the expression assigned to secondsPerWeek is a constant expression because all the operands in the expression are also constants.

C# 10 added support for constant interpolated strings whereby you can define a constant string with interpolation if it is comprised solely of other constant strings and, as such, it can be evaluated at compile time (see Listing 4.20 ).

Even though announcement in Listing 4.20 is an interpolated string, the values within the code portions of the string are also constants, enabling the compiler to evaluate them at compile time rather than waiting until execution time. Also note, however, that windspeed is a string, not an integer. Constant string interpolation works when formed solely of other constant strings, not of other data types even if those types are constant. The restriction is to allow conversion to a string to account for culture variation at execution time. For example, converting the golden ratio to a string could be 1.6180339887 or 1,6180339887 depending on the culture.

________________________________________

  • p.key == item.key) && !currentPage.some(p => p.level > item.level), }" > p.key == item.key) && !currentPage.some(p => p.level > item.level), }" :href="item.href"> Introduction
  • p.key == item.key) && !currentPage.some(p => p.level > item.level), }" > p.key == item.key), }" :href="item.href"> {{item.title}}

BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy . This message is for compliance with the UK ICO law .

C# Programming

C# Compound Assignment Operators

The seventh part of the C# Fundamentals tutorial extends knowledge of the assignment operator into compound assignment operators. These operators permit modification of variable values using the arithmetic functions described earlier in the tutorial.

The Assignment Operator

The basic assignment operator (=) was reviewed in the third part of the C# Fundamentals tutorial . This operator is used to assign value to variables. We have used the operator in every part of the tutorial since, so no further explanation is necessary.

Compound Assignment Operators

There are further assignment operators that can be used to modify the value of an existing variable. These are the compound assignment operators . A compound assignment operator is used to simplify the coding of some expressions. For example, using the operators described earlier we can increase a variable's value by ten using the following code:

This statement has an equivalent using the compound assignment operator for addition (+=).

There are compound assignment operators for each of the five binary arithmetic operators (+ - * / %) that we have investigated so far in the tutorial. Each is constructed using the arithmetic operator followed by the assignment operator. The following code gives examples for addition (+=), subtraction (-=), multiplication (*=), division (/=) and modulus (%=):

Compound assignment operators provide two benefits. Firstly, they produce more compact code; they are often called shorthand operators for this reason. Secondly, the variable being operated upon, or operand , will only be evaluated once in the compiled application. This can make the code more efficient.

Operator Precedence

The assignment operator and the compound assignment operators have the lowest priority; they appear at the end of the operator precedence table.

RSS Feed

Microsoft Visual C# Step by Step, 10th Edition by John Sharp

Get full access to Microsoft Visual C# Step by Step, 10th Edition and 60K+ other titles, with a free 10-day trial of O'Reilly.

There are also live events, courses curated by job role, and more.

Using compound assignment and iteration statements

After completing this chapter, you will be able to:

Update the value of a variable by using compound assignment operators.

Write while , for , and do iteration statements.

Step through a do statement and watch as the values of variables change.

Chapter 4 , “ Using decision statements ,” demonstrated how to use the if and switch constructs to run statements selectively. In this chapter, you’ll see how to use a variety of iteration (or looping) statements to run one or more statements repeatedly.

When you write iteration statements, you usually need to control the number of iterations you perform. You can achieve this by using a variable, updating its value as each iteration is performed, ...

Get Microsoft Visual C# Step by Step, 10th Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.

Don’t leave empty-handed

Get Mark Richards’s Software Architecture Patterns ebook to better understand how to design components—and how they should interact.

It’s yours, free.

Cover of Software Architecture Patterns

Check it out now on O’Reilly

Dive in for free with a 10-day trial of the O’Reilly learning platform—then explore all the other resources our members count on to build skills and solve problems every day.

compound assignment c#

  • PyQt5 ebook
  • Tkinter ebook
  • SQLite Python
  • wxPython ebook
  • Windows API ebook
  • Java Swing ebook
  • Java games ebook
  • MySQL Java ebook

C# operator

last modified July 5, 2023

In this article we cover C# operators.

Expressions are constructed from operands and operators. The operators of an expression indicate which operations to apply to the operands. The order of evaluation of operators in an expression is determined by the precedence and associativity of the operators.

An operator is a special symbol which indicates a certain process is carried out. Operators in programming languages are taken from mathematics. Programmers work with data. The operators are used to process data. An operand is one of the inputs (arguments) of an operator.

C# operator list

The following table shows a set of operators used in the C# language.

An operator usually has one or two operands. Those operators that work with only one operand are called unary operators . Those who work with two operands are called binary operators . There is also one ternary operator ?: , which works with three operands.

Certain operators may be used in different contexts. For example the + operator. From the above table we can see that it is used in different cases. It adds numbers, concatenates strings or delegates; indicates the sign of a number. We say that the operator is overloaded .

C# unary operators

C# unary operators include: +, -, ++, --, cast operator (), and negation !.

C# sign operators

There are two sign operators: + and - . They are used to indicate or change the sign of a value.

The + and - signs indicate the sign of a value. The plus sign can be used to indicate that we have a positive number. It can be omitted and it is mostly done so.

The minus sign changes the sign of a value.

C# increment and decrement operators

Incrementing or decrementing a value by one is a common task in programming. C# has two convenient operators for this: ++ and -- .

The above two pairs of expressions do the same.

In the above example, we demonstrate the usage of both operators.

We initiate the x variable to 6. Then we increment x two times. Now the variable equals to 8.

We use the decrement operator. Now the variable equals to 7.

C# explicit cast operator

The explicit cast operator () can be used to cast a type to another type. Note that this operator works only on certain types.

In the example, we explicitly cast a float type to int .

Negation operator

The negation operator (!) reverses the meaning of its operand.

In the example, we build a negative condition: it is executed if the inverse of the expression is valid.

C# assignment operator

The assignment operator = assigns a value to a variable. A variable is a placeholder for a value. In mathematics, the = operator has a different meaning. In an equation, the = operator is an equality operator. The left side of the equation is equal to the right one.

Here we assign a number to the x variable.

The previous expression does not make sense in mathematics. But it is legal in programming. The expression adds 1 to the x variable. The right side is equal to 2 and 2 is assigned to x .

This code example results in syntax error. We cannot assign a value to a literal.

C# concatenating strings

The + operator is also used to concatenate strings.

We join three strings together using string concatenation operator.

C# arithmetic operators

The following is a table of arithmetic operators in C#.

The following example shows arithmetic operations.

In the preceding example, we use addition, subtraction, multiplication, division, and remainder operations. This is all familiar from the mathematics.

The % operator is called the remainder or the modulo operator. It finds the remainder of division of one number by another. For example, 9 % 4 , 9 modulo 4 is 1, because 4 goes into 9 twice with a remainder of 1.

Next we show the distinction between integer and floating point division.

In the preceding example, we divide two numbers.

In this code, we have done integer division. The returned value of the division operation is an integer. When we divide two integers the result is an integer.

If one of the values is a double or a float, we perform a floating point division. In our case, the second operand is a double so the result is a double.

C# Boolean operators

In C#, we have three logical operators. The bool keyword is used to declare a Boolean value.

Boolean operators are also called logical.

Many expressions result in a boolean value. Boolean values are used in conditional statements.

Relational operators always result in a boolean value. These two lines print false and true.

The body of the if statement is executed only if the condition inside the parentheses is met. The y > x returns true, so the message "y is greater than x" is printed to the terminal.

The true and false keywords represent boolean literals in C#.

Example shows the logical and operator. It evaluates to true only if both operands are true.

Only one expression results in True .

The logical or || operator evaluates to true, if either of the operands is true.

If one of the sides of the operator is true, the outcome of the operation is true.

Three of four expressions result in true.

The negation operator ! makes true false and false true.

The example shows the negation operator in action.

The || , and && operators are short circuit evaluated. Short circuit evaluation means that the second argument is only evaluated if the first argument does not suffice to determine the value of the expression: when the first argument of the logical and evaluates to false, the overall value must be false; and when the first argument of logical or evaluates to true, the overall value must be true. Short circuit evaluation is used mainly to improve performance.

An example may clarify this a bit more.

We have two methods in the example. They are used as operands in boolean expressions.

The One method returns false . The short circuit && does not evaluate the second method. It is not necessary. Once an operand is false , the result of the logical conclusion is always false . Only "Inside one" is only printed to the console.

In the second case, we use the || operator and use the Two method as the first operand. In this case, "Inside two" and "Pass" strings are printed to the terminal. It is again not necessary to evaluate the second operand, since once the first operand evaluates to true , the logical or is always true .

C# relational operators

Relational operators are used to compare values. These operators always result in boolean value.

Relational operators are also called comparison operators.

In the code example, we have four expressions. These expressions compare integer values. The result of each of the expressions is either true or false. In C# we use == to compare numbers. Some languages like Ada, Visual Basic, or Pascal use = for comparing numbers.

C# bitwise operators

Decimal numbers are natural to humans. Binary numbers are native to computers. Binary, octal, decimal, or hexadecimal symbols are only notations of the same number. Bitwise operators work with bits of a binary number. Bitwise operators are seldom used in higher level languages like C#.

The bitwise negation operator changes each 1 to 0 and 0 to 1.

The operator reverts all bits of a number 7. One of the bits also determines, whether the number is negative or not. If we negate all the bits one more time, we get number 7 again.

The bitwise and operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 only if both corresponding bits in the operands are 1.

The first number is a binary notation of 6, the second is 3, and the result is 2.

The bitwise or operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 if either of the corresponding bits in the operands is 1.

The result is 00110 or decimal 7.

The bitwise exclusive or operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 if one or the other (but not both) of the corresponding bits in the operands is 1.

The result is 00101 or decimal 5.

C# compound assignment operators

The compound assignment operators consist of two operators. They are shorthand operators.

The += compound operator is one of these shorthand operators. The above two expressions are equal. Value 3 is added to the a variable.

Other compound operators are:

In the example, we use two compound operators.

The a variable is initiated to one. 1 is added to the variable using the non-shorthand notation.

Using a += compound operator, we add 5 to the a variable. The statement is equal to a = a + 5; .

Using the *= operator, the a is multiplied by 3. The statement is equal to a = a * 3; .

C# new operator

The new operator is used to create objects and invoke constructors.

In the example, we create a new custom object and a array of integers utilizing the new operator.

This is a constructor. It is called at the time of the object creation.

C# access operator

The access operator [] is used with arrays, indexers, and attributes.

In the example, we use the [] operator to get an element of an array, value of a dictionary pair, and activate a built-in attribute.

We define an array of integers. We get the first element with vals[0] .

A dictionary is created. With domains["de"] , we get the value of the pair that has the "de" key.

We active the built-in Obsolete attribute. The attribute issues a warning.

When we run the program, it produces the warning: warning CS0618: 'oldMethod()' is obsolete: 'Don't use OldMethod, use NewMethod instead' .

C# index from end operator ^

The index from end operator ^ indicates the element position from the end of a sequence. For instance, ^1 points to the last element of a sequence and ^n points to the element with offset length - n .

In the example, we apply the operator on an array and a string.

We print the last and the last but one element of the array.

We print the last letter of the word.

C# range operator ..

The .. operator specifies the start and end of a range of indices as its operands. The left-hand operand is an inclusive start of a range. The right-hand operand is an exclusive end of a range.

Operands of the .. operator can be omitted to get an open-ended range.

In the example, we use the .. operator to get array slices.

We create an array slice from index 1 till index 4; the last index 4 is not included.

Here we esentially create a copy of the array.

C# type information

Now we concern ourselves with operators that work with types.

The sizeof operator is used to obtain the size in bytes for a value type. The typeof is used to obtain the System.Type object for a type.

We use the sizeof and typeof operators.

We can see that the int type is an alias for System.Int32 and the float is an alias for the System.Single type.

The is operator checks if an object is compatible with a given type.

We create two objects from user defined types.

We have a Base and a Derived class. The Derived class inherits from the Base class.

Base equals Base and so the first line prints True. The Base is also compatible with Object type. This is because each class inherits from the mother of all classes — the Object class.

The derived object is compatible with the Base class because it explicitly inherits from the Base class. On the other hand, the _base object has nothing to do with the Derived class.

The as operator is used to perform conversions between compatible reference types. When the conversion is not possible, the operator returns null. Unlike the cast operation which raises an exception.

In the above example, we use the as operator to perform casting.

We try to cast various types to the string type. But only once the casting is valid.

C# operator precedence

The operator precedence tells us which operators are evaluated first. The precedence level is necessary to avoid ambiguity in expressions.

What is the outcome of the following expression, 28 or 40?

Like in mathematics, the multiplication operator has a higher precedence than addition operator. So the outcome is 28.

To change the order of evaluation, we can use parentheses. Expressions inside parentheses are always evaluated first.

The following table shows common C# operators ordered by precedence (highest precedence first):

Operators on the same row of the table have the same precedence.

In this code example, we show a few expressions. The outcome of each expression is dependent on the precedence level.

This line prints 28. The multiplication operator has a higher precedence than addition. First, the product of 5*5 is calculated, then 3 is added.

In this case, the negation operator has a higher precedence. First, the first true value is negated to false, then the | operator combines false and true, which gives true in the end.

C# associativity rule

Sometimes the precedence is not satisfactory to determine the outcome of an expression. There is another rule called associativity . The associativity of operators determines the order of evaluation of operators with the same precedence level.

What is the outcome of this expression, 9 or 1? The multiplication, deletion and the modulo operator are left to right associated. So the expression is evaluated this way: (9 / 3) * 3 and the result is 9.

Arithmetic, boolean, relational, and bitwise operators are all left to right associated.

On the other hand, the assignment operator is right associated.

In the example, we have two cases where the associativity rule determines the expression.

The assignment operator is right to left associated. If the associativity was left to right, the previous expression would not be possible.

The compound assignment operators are right to left associated. We might expect the result to be 1. But the actual result is 0. Because of the associativity. The expression on the right is evaluated first and than the compound assignment operator is applied.

C# null-conditional operator

A null-conditional operator applies a member access, ?. , or element access, ?[] , operation to its operand only if that operand evaluates to non-null. If the operand evaluates to null , the result of applying the operator is null.

In the example, we have a User class with two members: Name and Occupation . We access the name member of the objects with the help of the ?. operator.

We have a list of users. One of them is initialized with null values.

We use the ?. to access the Name member and call the ToUpper method. The ?. prevents the System.NullReferenceException by not calling the ToUpper on the null value.

In the following example, we use the ?[] operator. The operator allows to place null values into a collection.

In this example, we have a null value in an array. We prevent the System.NullReferenceException by applying the ?. operator on the array elements.

C# null-coalescing operator

The null-coalescing operator ?? is used to define a default value for a nullable type. It returns the left-hand operand if it is not null; otherwise it returns the right operand. When we work with databases, we often deal with absent values. These values come as nulls to the program. This operator is a convenient way to deal with such situations.

An example program for null-coalescing operator.

Two nullable int types are initiated to null . The int? is a shorthand for Nullable<int> . It allows to have null values assigned to int types.

We want to assign a value to z variable. But it must not be null . This is our requirement. We can easily use the null-coalescing operator for that. In case both x and y variables are null, we assign -1 to z .

C# null-coalescing assignment operator

The null-coalescing assignment operator ??= assigns the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates to null . The ??= operator does not evaluate its right-hand operand if the left-hand operand evaluates to non-null. It is available in C# 8.0 and later.

In the example, we use the null-coalescing assignment operator on a list of integer values.

First, the list is assigned to null .

We use the ??= to assign a new list object to the variable. Since it is null , the list is assigned.

We add some values to the list and print its contents.

We try to assign a new list object to the variable. Since the variable is not null anymore, the list is not assigned.

C# ternary operator

The ternary operator ?: is a conditional operator. It is a convenient operator for cases where we want to pick up one of two values, depending on the conditional expression.

If cond-exp is true, exp1 is evaluated and the result is returned. If the cond-exp is false, exp2 is evaluated and its result is returned.

In most countries the adulthood is based on your age. You are adult if you are older than a certain age. This is a situation for a ternary operator.

First the expression on the right side of the assignment operator is evaluated. The first phase of the ternary operator is the condition expression evaluation. So if the age is greater or equal to 18, the value following the ? character is returned. If not, the value following the : character is returned. The returned value is then assigned to the adult variable.

A 31 years old person is adult.

C# Lambda operator

The => token is called the lambda operator. It is an operator taken from functional languages. This operator can make the code shorter and cleaner. On the other hand, understanding the syntax may be tricky. Especially if a programmer never used a functional language before.

Wherever we can use a delegate, we also can use a lambda expression. A definition for a lambda expression is: a lambda expression is an anonymous function that can contain expressions and statements. On the left side we have a group of data and on the right side an expression or a block of statements. These statements are applied on each item of the data.

In lambda expressions we do not have a return keyword. The last statement is automatically returned. And we do not need to specify types for our parameters. The compiler will guess the correct parameter type. This is called type inference.

We have a list of integer numbers. We print all numbers that are greater than 3.

We have a generic list of integers.

Here we use the lambda operator. The FindAll method takes a predicate as a parameter. A predicate is a special kind of a delegate that returns a boolean value. The predicate is applied for all items of the list. The val is an input parameter specified without a type. We could explicitly specify the type but it is not necessary.

The compiler will expect an int type. The val is a current input value from the list. It is compared if it is greater than 3 and a boolean true or false is returned. Finally, the FindAll will return all values that met the condition. They are assigned to the sublist collection.

The items of the sublist collection are printed to the terminal.

Values from the list of integers that are greater than 3.

This is the same example. We use a anonymous delegate instead of a lambda expression.

C# calculating prime numbers

We are going to calculate prime numbers.

In the above example, we deal with many various operators. A prime number (or a prime) is a natural number that has exactly two distinct natural number divisors: 1 and itself. We pick up a number and divide it by numbers, from 1 up to the picked up number. Actually, we do not have to try all smaller numbers; we can divide by numbers up to the square root of the chosen number. The formula will work. We use the remainder division operator.

We calculate primes from these numbers.

By definition, 1 is not a prime

We skip the calculations for 2 and 3: they are primes. Note the usage of the equality and conditional or operators. The == has a higher precedence than the || operator. So we do not need to use parentheses.

We are OK if we only try numbers smaller than the square root of a number in question. It was mathematically proven that it is sufficient to take into account values up to the square root of the number in question.

This is a while loop. The i is the calculated square root of the number. We use the decrement operator to decrease the i by one each loop cycle. When the i is smaller than 1, we terminate the loop. For example, we have number 9. The square root of 9 is 3. We divide the 9 number by 3 and 2.

This is the core of the algorithm. If the remainder division operator returns 0 for any of the i values then the number in question is not a prime.

C# operators and expressions

In this article we covered C# operators.

My name is Jan Bodnar and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all C# tutorials .

compound assignment c#

  • Introduction to C#
  • Download and Install Visual Studio
  • The First C# Program
  • C# Data Types
  • C# variables, keywords , constants
  • C# If Statement
  • C# If Else Statement
  • C# Else If Statement
  • C# Nested If Statement
  • C# While Loop
  • C# Do While Loop
  • C# Break Statement
  • C# Continue Statement
  • C# Switch Statement
  • C# Goto Statement
  • C# Arithmetic Operator
  • C# Increment Operator
  • C# Decrement Operator
  • C# Compound Assignment Operator
  • C# Relational Operators
  • C# Logical Operators
  • C# Conditional Operator
  • C# is Operator
  • C# 2D Array
  • C# 3D Array
  • C# Jagged Array
  • C# Class and its members
  • C# Class Member Access Modifiers
  • C# Interface
  • C# Abstract Class
  • C# Method Return Types
  • C# This Keyword
  • C# Static Keyword
  • C# Polymorphism
  • C# Inheritance
  • C# Constructors
  • C# Destructors
  • C# Method Overloading
  • C# Method Overriding
  • C# Call By Value
  • C# Call By Reference
  • C# ref parameter
  • C# out parameter
  • C# Recursion
  • C# Garbage Collection
  • C# String Intern Pool
  • C# String Immutability
  • C# String Methods
  • C# String Comparison with ==
  • C# String Concat()
  • C# String Trim()
  • C# String ToUpper()
  • C# String ToLower()
  • C# String StartsWith
  • C# String EndsWith()
  • C# String Replace()
  • C# String Insert()
  • C# String Intern()
  • C# String Substring()
  • C# ToString() Method
  • C# String LastIndexOf()
  • C# String Equals()
  • C# String Split()
  • C# String Remove()
  • C# String Contains()
  • C# String Join()
  • C# What is Exception?
  • C# Exception Propagation
  • C# Try-Catch block
  • C# Multiple Catch Blocks
  • C# Nested TryCatch Block
  • C# Finally block
  • C# Throw Keyword
  • C# Checked and Unchecked Keywords
  • C# User Defined Exception
  • C# FileStream
  • C# FileMode and FileAccess
  • C# StreamWriter
  • C# StreamReader
  • C# TextWriter
  • C# TextReader
  • C# StringWriter
  • C# StringReader
  • C# BinaryWriter
  • C# BinaryReader
  • C# File Class
  • C# Directory Class
  • C# MemoryStream
  • C# Random Access Files
  • C# Serialization and Deserialization
  • C# Lifecycle of Thread
  • C# Creating a Thread
  • C# Passing an Argument to Thread
  • C# Creating Multiple Threads
  • C# Thread Priorities
  • C# Thread Join() Method
  • C# Thread Interrupt() Method
  • C# ThreadStateException in Thread
  • C# Thread Abort() Method
  • C# Thread Synchronization
  • C# Interthread Communication
  • C# Deadlock in Threads
  • C# ArrayList
  • C# Hashtable
  • C# SortedList
  • C# Generic SortedList
  • C# Generic Stack
  • C# Generic Queue
  • C# Generic LinkedList
  • C# Generic List
  • C# Generic HashSet
  • C# Generic Dictionary

Advertisement

+= operator

  • Add operation.
  • Assignment of the result of add operation.
  • Understanding += operator with a code -
  • Statement i+=2 is equal to i=i+2 , hence 2 will be added to the value of i, which gives us 4.
  • Finally, the result of addition, 4 is assigned back to i, updating its original value from 2 to 4.
  • A special case scenario for all the compound assigned operators
  • All compound assignment operators perform implicit casting.
  • Casting the char value ( smaller data type ) to an int value( larger data type ), so it could be added to an int value, 2.
  • Finally, the result of performing the addition resulted in an int value, which was casted to a char value before it could be assigned to a char variable, ch .

Example with += operator

-= operator.

  • Subtraction operation.
  • Assignment of the result of subtract operation.
  • Statement i-=2 is equal to i=i-2 , hence, 2 will be subtracted from the value of i, which gives us 0.
  • Finally, the result of subtraction i.e. 0 is assigned back to i, updating its value to 0.

Example with -= operator

*= operator.

  • Multiplication operation.
  • Assignment of the result of multiplication operation.
  • Statement i*=2 is equal to i=i*2 , hence 2 will be multiplied with the value of i, which gives us 4.
  • Finally, the result of multiplication, 4 is assigned back to i, updating its value to 4.

Example with *= operator

/= operator.

  • Division operation.
  • Assignment of the result of division operation.
  • Statement i/=2 is equal to i=i/2 , hence 4 will be divided by the value of i, which gives us 2.
  • Finally, the result of division i.e. 2 is assigned back to i, updating its value from 4 to 2.

Example with /= operator

%= operator.

  • Modulus operation, which finds the remainder of a division operation.
  • Assignment of the result of modulus operation.
  • Statement i%=2 is equal to i=i%2 , hence 4 will be divided by the value of i and its remainder gives us 0.
  • Finally, the result of this modulus operation i.e. 0 is assigned back to i, updating its value from 4 to 0.

Example with %= operator

Please share this article -.

Facebook

Please Subscribe

Decodejava Facebook Page

Notifications

Please check our latest addition C#, PYTHON and DJANGO

© Copyright 2020 Decodejava.com. All Rights Reserved.

Compound Assignment in

About compound assignment.

Many operators can also be used as compound assignments , which are a shorthand notation where x = op y can be written as x op= y :

Trending Articles on Technical and Non Technical topics

  • Selected Reading
  • UPSC IAS Exams Notes
  • Developer's Best Practices
  • Questions and Answers
  • Effective Resume Writing
  • HR Interview Questions
  • Computer Glossary

Compound assignment operators in C#

A compound assignment operator has a shorter syntax to assign the result. The operation is performed on the two operands before the result is assigned to the first operand.

The following are the compound assignment operators in C#.

Let us see an example to learn how to work with compound assignment operators in C#.

 Live Demo

Samual Sam

Related Articles

  • Compound Assignment Operators in C++
  • Compound assignment operators in Java\n
  • Assignment Operators in C++
  • What are assignment operators in C#?
  • Perl Assignment Operators
  • Assignment operators in Dart Programming
  • Compound operators in Arduino
  • What is the difference between = and: = assignment operators?
  • Passing the Assignment in C++
  • Airplane Seat Assignment Probability in C++
  • What is an assignment operator in C#?
  • Copy constructor vs assignment operator in C++
  • Ternary Operators in C/C++
  • Unary operators in C/C++
  • Conversion Operators in C++

Kickstart Your Career

Get certified by completing the course

To Continue Learning Please Login

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications

Nondestructive assignment using = with { } #8114

@dmchurch

dmchurch May 12, 2024

Beta Was this translation helpful? Give feedback.

Replies: 2 comments · 3 replies

Colejohnson66 may 12, 2024.

@dmchurch

{{editor}}'s edit

Dmchurch may 12, 2024 author, iam3yal may 13, 2024, dmchurch may 13, 2024 author.

@iam3yal

  • Numbered list
  • Unordered list
  • Attach files

Select a reply

Microsoft Visual C# 2013 Step by Step by John Sharp

Get full access to Microsoft Visual C# 2013 Step by Step and 60K+ other titles, with a free 10-day trial of O'Reilly.

There are also live events, courses curated by job role, and more.

Chapter 5. Using compound assignment and iteration statements

After completing this chapter, you will be able to:

Using compound assignment operators

Writing while statements

Writing do statements

Chapter 4 demonstrates how to use the if and switch constructs to run statements selectively. In this chapter, you’ll see how to use a variety of iteration (or looping ) statements to run one or more statements repeatedly.

When you write iteration statements, you usually need to control the number of iterations that you perform. You can achieve this by using a variable, updating its value as each iteration is performed, and stopping the process when the variable reaches a particular value. To help simplify this process, you’ll start by learning about the special ...

Get Microsoft Visual C# 2013 Step by Step now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.

Don’t leave empty-handed

Get Mark Richards’s Software Architecture Patterns ebook to better understand how to design components—and how they should interact.

It’s yours, free.

Cover of Software Architecture Patterns

Check it out now on O’Reilly

Dive in for free with a 10-day trial of the O’Reilly learning platform—then explore all the other resources our members count on to build skills and solve problems every day.

compound assignment c#

compound assignment c#

Refactor your code with C# collection expressions

compound assignment c#

May 8th, 2024 10 9

This post is the second in a series of posts covering various refactoring scenarios that explore C# 12 features. In this post, we’ll look at how you can refactor your code using collection expressions, we’ll learn about collection initializers, various expression usages, supported collection target types, and the spread syntax. Here’s how the series is shaping up:

  • Refactor your C# code with primary constructors
  • Refactor your C# code with collection expressions (this post)
  • Refactor your C# code by aliasing any type
  • Refactor your C# code to use default lambda parameters

These features continue our journey to make our code more readable and maintainable, and these are considered “Everyday C#” features that developers should know.

Collection Expressions 🎨

C# 12 introduced collection expressions that offer a simple and consistent syntax across many different collection types. When initializing a collection with a collection expression, the compiler generates code that is functionally equivalent to using a collection initializer. The feature emphasizes consistency , while allowing for the compiler to optimize the lowered C#. Of course, every team decides what new features to adopt, and you can experiment and introduce this new syntax if you like it, since all of the previous ways to initialize collections will continue to work.

With collections expressions elements appear inlined sequences of elements between an opening [ and closing ] bracket. Read on to hear more about how collection expressions work.

Initialization 🌱

C# provides many syntaxes for initializing different collections. Collection expressions replace all of these, so let’s start with a look at different ways you can initialize an array of integers like this:

All four versions are functionally equivalent, and the compiler generates identical code for each version. The last example is similar to the new collection expressions syntax. If you squint your eyes a bit, you could imagine the curly braces as { and } as square brackets [ and ] , then you’d be reading the new collection expression syntax. Collection expressions don’t use curly braces. This is to avoid ambiguity with existing syntax, especially { } to indicate any not-null in patterns.

The last example is the only to declare the type explicitly, instead of relying on var . The following example creates a List<char> :

Again, collection expressions cannot be used with the var keyword. You must declare the type because a collection expression doesn’t currently have a natural type and can be converted to a wide variety of collection types . Supporting assignment to var is still under consideration, but the team has not settled on the what the natural type should be. In other words, the C# compiler errors out with CS9176: There is no target type for the collection expression, when writing the following code:

You might be asking yourself, “with all these different approaches to initializing collections, why would I use the new collection expression syntax?” The answer is that with collection expressions, you can use the same syntax to express collections in a consistent way. This can help to make your code more readable and maintainable. We’ll explore more advantages in the coming sections.

Collection expression variations 🎭

You can express that a collection is empty , using the following syntax:

The empty collection expression initialization is a great replacement for code that was otherwise using the new keyword, as it’s optimized by the compiler to avoid allocating memory for some collection types. For example, when the collection type is an array T[] , the compiler generates an Array.Empty<T>() , which is more efficient than new int[] { } . Another shortcut is to use the number of elements in the collection expression to set the collection size, such as new List<int>(2) for List<T> x = [1, 2]; .

Collection expressions also allow you to assign to interfaces without stating an explicit type. The compiler determines the type to use for types, such as IEnumerable<T> , IReadOnlyList<T> , and IReadOnlyCollection<T> . If the actual type used is important, you’ll want to state it because this may change if more efficient types become available. Likewise, in situations where the compiler cannot generate more efficient code, for example when the collection type is a List<T> , the compiler generates a new List<int>() , which is then equivalent.

The advantages of using the empty collection expression are threefold:

  • It provides a consistent means of initializing all collections, regardless of their target type.
  • It allows the compiler to generate efficient code.
  • It’s less code to write. For example, instead of writing Array.Empty<T>() or Enumerable.Empty<T>() , you can simply write [] .

A few more details about the efficient generated code: using the [] syntax generates known IL. This allows the runtime to optimize by reusing the storage for Array.Empty<T> (for each T ), or even more aggressively inline the code.

Empty collections serve their purpose, but you may need a collection that has some initial values. You can initialize a collection with a single element, using the following syntax:

Initializing a single element collection is similar to initializing a collection with more than a single element. You can initialize a collection with multiple elements by adding other literal values, using the following syntax:

A bit of history

Let’s look at another code sample, but this uses spread element , to include the elements of another collection, using the following syntax:

The spread element is a powerful feature that allows you to include the elements of another collection in the current collection. The spread element is a great way to combine collections in a concise way. The expression in a spread element must be enumerable ( foreach -able). For more information, see the Spread ✨ section.

Supported collection types 🎯

There are many target types that collection expressions can be used with. The feature recognizes the “shape” of a type that represents a collection. Therefore, most collections you’re familiar with are supported out-of-the-box. For types that don’t match that “shape” (mostly readonly collections), there are attributes you can apply to describe the builder pattern. The collection types in the BCL that needed the attributes/builder pattern approaches, have already been updated.

It’s unlikely that you’ll ever need to think about how target types are selected, but if you are curious about the rules see the C# Language Reference: Collection expressions—conversions .

Collection expressions don’t yet support dictionaries. You can find a proposal to extend the feature C# Feature Proposal: Dictionary expressions .

Refactoring scenarios 🛠️

Collection expressions can be useful in many scenarios, such as:

  • properties.
  • local variables.
  • method parameters.
  • return values.
  • a coalescing expression as the final fallthrough to safely avoid exceptions.
  • Passing arguments to methods that expect collection type parameters.

Let’s use this section to explore some sample usage scenarios, and consider potential refactoring opportunities. When you define a class or struct that contains fields and/or properties with non-nullable collection types, you can initialize them with collection expressions. For example, consider the following example ResultRegistry object:

In the preceding code, the result registry class contains a private _results field that is initialized with a new HashSet<Result>() constructor expression. In your IDE of choice (that supports these refactoring features), right-click on the new keyword, select Quick Actions and Refactorings... (or press Ctrl + . ), and choose Collection initialization can be simplified , as shown in the following video:

The code is updated to use the collection expression syntax, as shown in the following code:

The previous code, instantiated the HashSet<Result> with the new HashSet<Result>() constructor expression. However, in this case [] is identical.

Many popular programming languages such as Python and JavaScript/TypeScript, among others provide their variation of the spread syntax, which serves as a succinct way to work with collections. In C#, the spread element is the syntax used to express the concatenation of various collections into a single collection.

Proper terminology

So what exactly is spread element ? It takes the individual values from the collection being “spread” and places them in the destination collection at that position. The spread element functionality also comes with a refactoring opportunity. If you have code that calls .ToList or .ToArray , or you want to use eager evaluation, your IDE might be suggesting to use the spread element syntax instead. For example, consider the following code:

The preceding code could be refactored to use the spread element syntax, consider the following code that removes the .ToList method call, and uses an expression-bodied method as a bonus refactored version:

Span<T> and ReadOnlySpan<T> support 📏

Collection expressions support Span<T> and ReadOnlySpan<T> types that are used to represent a contiguous region of arbitrary memory. You benefit from the performance improvements they offer, even if you don’t use them directly in your code. Collection expressions allow the runtime to offer optimizations, especially where overloads using span can be selected when collection expressions are used as arguments.

You can also assign directly to span, if your application uses spans:

If you’re using the stackalloc keyword, there’s even a provided refactoring to use collection expressions. For example, consider the following code:

If you right-click on the stackalloc keyword, select Quick Actions and Refactorings... (or press Ctrl + . ), and choose Collection initialization can be simplified , as shown in the following video:

https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/05/refactor-collection-ex.mp4

For more information, see Memory<T> and Span<T> usage guidelines .

Semantic considerations ⚙️

When initializing a collection with a collection expression, the compiler generates code that is functionally equivalent to using a collection initializer. Sometimes the generated code is much more efficient than using a collection initializer. Consider the following example:

The rules for a collection initializer require that the compiler call the Add method for each element in the initializer. However, if you’re to use the collection expression syntax:

The compiler generates code that instead uses AddRange , that might be faster or better optimized. The compiler is able to make these optimizations because it knows the target type of the collection expression.

Next steps 🚀

Be sure to try this out in your own code! Check back soon for the next post in this series, where we’ll explore how to refactor your C# code by aliasing any type. In the meantime, you can learn more about collection expressions in the following resources:

  • C# Feature Proposal: Collection expressions
  • C# Language Reference: Collection expressions
  • C# Docs: Collections

compound assignment c#

David Pine Senior Content Developer, .NET

compound assignment c#

10 comments

Leave a comment cancel reply.

Log in to join the discussion or edit/delete existing comments.

This is all extremely nice!

This is a neat implementation of the Collection expression.

IMHO this is the annoying part of the feature Again, collection expressions cannot be used with the var keyword.

hope this will be addressed sooner then later, and if that’s all the reason behind it but the team has not settled on the what the natural type should be.

roll a dice if you can’t make up your mind. Or put up a poll and let majority decide.

I disagree. var support is not needed.

If anyone is wondering, the question is which is the correct choice when var is used: a) Default to the fastest and most efficient, such as Span or ReadOnlySpan b) Default to the one with the best developer experience, such as List

You can argue both cases, so it is just hard for everyone to reach agreement here.

Love or hate the collection expressions, but the use of emojis here is world class.

Regarding the LINQ example with the spread operator: does use of the collection expression result in the same call to .ToList() or is there some additional optimization going on? The original code could have been written as expression-bodied member as well, without declaring a local variable, so the new syntax isn’t much shorter and arguably the intent isn’t really clearer either. I wouldn’t use collection expressions in that case, unless perhaps it’s more efficient – hence the question.

(that aside, a very useful feature! the spread operator will replace a bunch of help methods in our code that were used to combine individual items and lists into a single list in an efficient manner, glad to let the compiler do that now)

This feature should come with a big warning: HERE BE DRAGONS

You don’t know if the compiler team has chosen the optimal code generation strategy or if the generated code is a fallback to just work. Best example is that on release this did generate the worst possible code for efcore DbSet .ToList(). I don’t know if this is already fixed.

I have a question on Spread .

I agree .. is not really an operator, just noticed Collection expressions (official documentation) is referring .. as spread operator.

It’s very important that we maintain correct terminology across.

compound assignment c#

Hi Jaliya, yes, you’re correct that we need to update the docs. Good catch. Thank you

light-theme-icon

Insert/edit link

Enter the destination URL

Or link to existing content

IMAGES

  1. C# Compound Assignment Operators

    compound assignment c#

  2. Answered: Pick out the compound assignment…

    compound assignment c#

  3. 025 Compound assignment operators (Welcome to the course C programming)

    compound assignment c#

  4. Chapter 5. Using compound assignment and iteration statements

    compound assignment c#

  5. c#

    compound assignment c#

  6. Exploring Compound Assignment Operators in C

    compound assignment c#

VIDEO

  1. Multiplication Table c# Project

  2. Compound Assignment Operators in C++ || C++ Programming #viral #subscribe

  3. Day 8

  4. MAT112 GROUP ASSIGNMENT

  5. GROUP ASSIGNMENT MAT112 (COMPOUND INTEREST & ANNUITY)

  6. Group Assignment MAT 112: compound interest and annuity

COMMENTS

  1. Assignment operators

    The left-hand operand of ref assignment can be a local reference variable, a ref field, and a ref, out, or in method parameter. Both operands must be of the same type. Compound assignment. For a binary operator op, a compound assignment expression of the form. x op= y is equivalent to. x = x op y except that x is only evaluated once.

  2. c#

    myFactory.GetNextObject().MyProperty += 5; You _certainly wouldn't do. myFactory.GetNextObject().MyProperty = myFactory.GetNextObject().MyProperty + 5; You could again use a temp variable, but the compound assignment operator is obviously more succinct. Granted, these are edge cases, but it's not a bad habit to get into.

  3. Coalescing operator and Compound assignment operator in C#

    Hello! Today i want to ask you this: Have you ever used a Null Coalescing operator or even a Compound assignment operator in C# ? I never. Until today i had never heard about this things, so i want to share with you what i learned about and how it can be applied to your code. The problem Let's say you want to give a given variable the value of ...

  4. C# 8

    There are a lot of cool new features in C# 8 and one of my favorites is the new Null coalescing assignment (or compound assignment, whichever you prefer) operator. If you have ever written code like this: private string _someValue; public string SomeMethod() { // Let's do an old-school null check and initialize if needed.

  5. Essential C#: Compound Mathematical Assignment Operators

    In C#, only assignment, call, increment, decrement, await, and object creation expressions are allowed to be the entirety of a statement. ... Compound mathematical assignment operators combine common binary operator calculations with the assignment operator. For example, consider Listing 4.10. Listing 4.10: Common Increment Calculation . int x ...

  6. C# Compound Assignment Operators

    A compound assignment operator is used to simplify the coding of some expressions. For example, using the operators described earlier we can increase a variable's value by ten using the following code: value = value + 10; This statement has an equivalent using the compound assignment operator for addition (+=). value += 10;

  7. Using compound assignment and iteration statements

    Chapter 5 Using compound assignment and iteration statements After completing this chapter, you will be able to: Update the value of a variable by using compound assignment operators. ... Get Microsoft Visual C# Step by Step, 10th Edition now with the O'Reilly learning platform. O'Reilly members experience books, live events, ...

  8. C# operator

    The compound assignment operators are right to left associated. We might expect the result to be 1. But the actual result is 0. Because of the associativity. The expression on the right is evaluated first and than the compound assignment operator is applied. $ dotnet run 0 0 0 0 0 C# null-conditional operator

  9. C# Compound Assignment Operator

    A special case scenario for all the compound assigned operators. int i= 2 ; i+= 2 * 2 ; //equals to, i = i+(2*2); In all the compound assignment operators, the expression on the right side of = is always calculated first and then the compound assignment operator will start its functioning. Hence, in the last code, statement i+=2*2; is equal to ...

  10. Compound Assignment in C# on Exercism

    Master Compound Assignment in C# by solving exercises, with support from our world-class team. Learn. Language Tracks. Upskill in 65+ languages #48in24 Challenge. A different challenge each week in 2024. Your Journey. Explore your Exercism journey. ... Compound Assignment in.

  11. Use compound assignment (IDE0054 and IDE0074)

    This style rule concerns with the use of compound assignments. The option value specifies whether or not they are desired. IDE0074 is reported for coalesce compound assignments and IDE0054 for other compound assignments. \n dotnet_style_prefer_compound_assignment \n

  12. Compound assignment operators in C#

    Print Page. Compound assignment operators in C - A compound assignment operator has a shorter syntax to assign the result. The operation is performed on the two operands before the result is assigned to the first operand.The following are the compound assignment operators in C#.Sr.NoOperator & Operator Name1+=Addition Assignment2-=Subtraction Assi.

  13. Nondestructive assignment using = with { } #8114

    The first example, despite being of exactly the form <expr> = <expr> with { <field> = <value> };, has a severe bug which could go uncaught for a long time and cause all sorts of grief, especially if the Renderers array doesn't have a deterministic order. The compound assignment version avoids that entirely. Pop quiz: are you certain you know which ++ should be removed from the first example to ...

  14. 5. Using compound assignment and iteration statements

    Chapter 5. Using compound assignment and iteration statements After completing this chapter, you will be able to: Using compound assignment operators Writing while statements Writing do statements Chapter 4 demonstrates … - Selection from Microsoft Visual C# 2013 Step by Step [Book]

  15. c#

    See Compound Assignment. For a binary operator op, a compound assignment expression of the form: x += y. is equivalent to. x = x + y. It simply makes your code more compact and (arguably) more readable. answered Mar 31, 2023 at 3:32. Luke Vo.

  16. Refactor your code with C# collection expressions

    The spread element is often confused with the term "spread operator". In C#, there's no such thing as a "spread operator". The .. expression isn't an operator, it's an expression that's part of the spread element syntax. By definition, this syntax doesn't align with that of an operator, as it doesn't perform an operation on its operands.

  17. Why are there no ||= or &&= operators in C#?

    The || and && operators do not have a compound form because frankly, they're a bit silly. Under what circumstances would you want to say Under what circumstances would you want to say b1 ||= b2; b1 &&= b2;