C#idiomatic C#
operatorscsharp/language-reference

Language

C# operators and expressions

Learn the C# operators and expressions, operator precedence, and operator associativity.

  • page csharp/language-reference/operators
  • updated 01/20/2026

C# provides many operators. The built-in types support many of these operators, so you can perform basic operations with values of those types.


ms.custom: "updateeachrelease"

The C# language reference documents the most recently released version of the C# language. It also contains initial documentation for features in public previews for the upcoming language release.

The documentation identifies any feature first introduced in the last three versions of the language or in current public previews.

These operators include the following groups:

Typically, you can overload these operators. By overloading an operator, you specify the operator behavior for the operands of a user-defined type.

The simplest C# expressions are literals (for example, integer and real numbers) and names of variables. You can combine them into complex expressions by using operators. Operator precedence and associativity determine the order in which the operations in an expression are performed. You can use parentheses to change the order of evaluation imposed by operator precedence and associativity.

In the following code, examples of expressions appear on the right-hand side of assignments:

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/Overview.csExpressions

csharp
namespace operators;

public static class Overview
{
    public static void Examples()
    {
        GeneralExamples();
        InterpolatedString();
        Lambda();
        Query();
    }

    private static readonly int[] collection = [1, 2, 3];

    private static void GeneralExamples()
    {
        // <SnippetExpressions>
        int a, b, c;
        a = 7;
        b = a;
        c = b++;
        b = a + b * c;
        c = a >= 100 ? b : c / 10;
        a = (int)Math.Sqrt(b * b + c * c);
        
        string s = "String literal";
        char l = s[s.Length - 1];

        List<int> numbers = [..collection];
        b = numbers.FindLast(n => n > 1);
        // </SnippetExpressions>
    }

    private static void InterpolatedString()
    {
        // <SnippetInterpolatedString>
        var r = 2.3;
        var message = $"The area of a circle with radius {r} is {Math.PI * r * r:F3}.";
        Console.WriteLine(message);
        // Output:
        // The area of a circle with radius 2.3 is 16.619.
        // </SnippetInterpolatedString>
    }

    private static void Lambda()
    {
        // <SnippetLambda>
        int[] numbers = { 2, 3, 4, 5 };
        var maximumSquare = numbers.Max(x => x * x);
        Console.WriteLine(maximumSquare);
        // Output:
        // 25
        // </SnippetLambda>
    }

    private static void Query()
    {
        // <SnippetQuery>
        int[] scores = { 90, 97, 78, 68, 85 };
        IEnumerable<int> highScoresQuery =
            from score in scores
            where score > 80
            orderby score descending
            select score;
        Console.WriteLine(string.Join(" ", highScoresQuery));
        // Output:
        // 97 90 85
        // </SnippetQuery>
    }
}

Typically, an expression produces a result and can be included in another expression. A void method call is an example of an expression that doesn't produce a result. It can be used only as a statement, as the following example shows:

csharp
Console.WriteLine("Hello, world!");

Here are some other kinds of expressions that C# provides:

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/Overview.csInterpolatedString

csharp
namespace operators;

public static class Overview
{
    public static void Examples()
    {
        GeneralExamples();
        InterpolatedString();
        Lambda();
        Query();
    }

    private static readonly int[] collection = [1, 2, 3];

    private static void GeneralExamples()
    {
        // <SnippetExpressions>
        int a, b, c;
        a = 7;
        b = a;
        c = b++;
        b = a + b * c;
        c = a >= 100 ? b : c / 10;
        a = (int)Math.Sqrt(b * b + c * c);
        
        string s = "String literal";
        char l = s[s.Length - 1];

        List<int> numbers = [..collection];
        b = numbers.FindLast(n => n > 1);
        // </SnippetExpressions>
    }

    private static void InterpolatedString()
    {
        // <SnippetInterpolatedString>
        var r = 2.3;
        var message = $"The area of a circle with radius {r} is {Math.PI * r * r:F3}.";
        Console.WriteLine(message);
        // Output:
        // The area of a circle with radius 2.3 is 16.619.
        // </SnippetInterpolatedString>
    }

    private static void Lambda()
    {
        // <SnippetLambda>
        int[] numbers = { 2, 3, 4, 5 };
        var maximumSquare = numbers.Max(x => x * x);
        Console.WriteLine(maximumSquare);
        // Output:
        // 25
        // </SnippetLambda>
    }

    private static void Query()
    {
        // <SnippetQuery>
        int[] scores = { 90, 97, 78, 68, 85 };
        IEnumerable<int> highScoresQuery =
            from score in scores
            where score > 80
            orderby score descending
            select score;
        Console.WriteLine(string.Join(" ", highScoresQuery));
        // Output:
        // 97 90 85
        // </SnippetQuery>
    }
}

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/Overview.csLambda

csharp
namespace operators;

public static class Overview
{
    public static void Examples()
    {
        GeneralExamples();
        InterpolatedString();
        Lambda();
        Query();
    }

    private static readonly int[] collection = [1, 2, 3];

    private static void GeneralExamples()
    {
        // <SnippetExpressions>
        int a, b, c;
        a = 7;
        b = a;
        c = b++;
        b = a + b * c;
        c = a >= 100 ? b : c / 10;
        a = (int)Math.Sqrt(b * b + c * c);
        
        string s = "String literal";
        char l = s[s.Length - 1];

        List<int> numbers = [..collection];
        b = numbers.FindLast(n => n > 1);
        // </SnippetExpressions>
    }

    private static void InterpolatedString()
    {
        // <SnippetInterpolatedString>
        var r = 2.3;
        var message = $"The area of a circle with radius {r} is {Math.PI * r * r:F3}.";
        Console.WriteLine(message);
        // Output:
        // The area of a circle with radius 2.3 is 16.619.
        // </SnippetInterpolatedString>
    }

    private static void Lambda()
    {
        // <SnippetLambda>
        int[] numbers = { 2, 3, 4, 5 };
        var maximumSquare = numbers.Max(x => x * x);
        Console.WriteLine(maximumSquare);
        // Output:
        // 25
        // </SnippetLambda>
    }

    private static void Query()
    {
        // <SnippetQuery>
        int[] scores = { 90, 97, 78, 68, 85 };
        IEnumerable<int> highScoresQuery =
            from score in scores
            where score > 80
            orderby score descending
            select score;
        Console.WriteLine(string.Join(" ", highScoresQuery));
        // Output:
        // 97 90 85
        // </SnippetQuery>
    }
}

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/Overview.csQuery

csharp
namespace operators;

public static class Overview
{
    public static void Examples()
    {
        GeneralExamples();
        InterpolatedString();
        Lambda();
        Query();
    }

    private static readonly int[] collection = [1, 2, 3];

    private static void GeneralExamples()
    {
        // <SnippetExpressions>
        int a, b, c;
        a = 7;
        b = a;
        c = b++;
        b = a + b * c;
        c = a >= 100 ? b : c / 10;
        a = (int)Math.Sqrt(b * b + c * c);
        
        string s = "String literal";
        char l = s[s.Length - 1];

        List<int> numbers = [..collection];
        b = numbers.FindLast(n => n > 1);
        // </SnippetExpressions>
    }

    private static void InterpolatedString()
    {
        // <SnippetInterpolatedString>
        var r = 2.3;
        var message = $"The area of a circle with radius {r} is {Math.PI * r * r:F3}.";
        Console.WriteLine(message);
        // Output:
        // The area of a circle with radius 2.3 is 16.619.
        // </SnippetInterpolatedString>
    }

    private static void Lambda()
    {
        // <SnippetLambda>
        int[] numbers = { 2, 3, 4, 5 };
        var maximumSquare = numbers.Max(x => x * x);
        Console.WriteLine(maximumSquare);
        // Output:
        // 25
        // </SnippetLambda>
    }

    private static void Query()
    {
        // <SnippetQuery>
        int[] scores = { 90, 97, 78, 68, 85 };
        IEnumerable<int> highScoresQuery =
            from score in scores
            where score > 80
            orderby score descending
            select score;
        Console.WriteLine(string.Join(" ", highScoresQuery));
        // Output:
        // 97 90 85
        // </SnippetQuery>
    }
}

You can use an expression body definition to provide a concise definition for a method, constructor, property, indexer, or finalizer.

Operator precedence

In an expression with multiple operators, the operators with higher precedence are evaluated before the operators with lower precedence. Operators of the same precedence are evaluated in lexical order. In the following example, the multiplication is performed first because it has higher precedence than addition:

csharp
var a = 2 + 2 * 2;
Console.WriteLine(a); //  output: 6

Use parentheses to change the order of evaluation imposed by operator precedence:

csharp
var a = (2 + 2) * 2;
Console.WriteLine(a); //  output: 8

The following table lists the C# operators starting with the highest precedence to the lowest. The operators within each row have the same precedence.

Operators Category or name
x.y, f(x), a[i], x?.y, x?[y], x++, x--, x!, new, typeof, checked, unchecked, default, nameof, delegate, sizeof, stackalloc, x->y Primary
+x, -x, !x, ~x, ++x, --x, ^x, (T)x, await, &x, *x, true and false Unary
x..y Range
switch, with switch and with expressions
x * y, x / y, x % y Multiplicative
x + y, x – y Additive
x << y, x >> y, x >>> y Shift
x < y, x > y, x <= y, x >= y, is, as Relational and type-testing
x == y, x != y Equality
x & y Boolean logical AND or bitwise logical AND
x ^ y Boolean logical XOR or bitwise logical XOR
x | y Boolean logical OR or bitwise logical OR
x && y Conditional AND
x || y Conditional OR
x ?? y Null-coalescing operator
c ? t : f Conditional operator
x = y, x += y, x -= y, x *= y, x /= y, x %= y, x &= y, x |= y, x ^= y, x <<= y, x >>= y, x >>>= y, x ??= y, => Assignment and lambda declaration

For information about the precedence of logical pattern combinators, see the Precedence and order of checking of logical patterns section of the Patterns article.

Operator associativity

When operators have the same precedence, associativity of the operators determines the order in which the operations are performed:

  • Left-associative operators are evaluated in order from left to right. Except for the assignment operators and the null-coalescing operators, all binary operators are left-associative. For example, a + b - c is evaluated as (a + b) - c.
  • Right-associative operators are evaluated in order from right to left. The assignment operators, the null-coalescing operators, lambdas, and the conditional operator ?: are right-associative. For example, x = y = z is evaluated as x = (y = z).

Use parentheses to change the order of evaluation imposed by operator associativity:

csharp
int a = 13 / 5 / 2;
int b = 13 / (5 / 2);
Console.WriteLine($"a = {a}, b = {b}");  // output: a = 1, b = 6

Operand evaluation

Unrelated to operator precedence and associativity, operands in an expression are evaluated from left to right. The following examples demonstrate the order in which operators and operands are evaluated:

Expression Order of evaluation
a + b a, b, +
a + b * c a, b, c, *, +
a / b + c * d a, b, /, c, d, *, +
a / (b + c) * d a, b, c, +, /, d, *

Typically, all operator operands are evaluated. However, some operators evaluate operands conditionally. That condition means the value of the leftmost operand of such an operator defines if (or which) other operands should be evaluated. These operators are the conditional logical AND (&&) and OR (||) operators, the null-coalescing operators ?? and ??=, the null-conditional operators ?. and ?[], and the conditional operator ?:. For more information, see the description of each operator.

C# language specification

For more information, see the following sections of the C# language specification:

See also