C# Expressions

C# Expressions

Understand expressions, and use-cases in C#

In computer science, an expression is a combination of constants, variables, and operators that evaluates to a single value. Expressions are used in:

  • Assignment statements: To assign a value to a variable.
int x = 5 + 6;  // Expression on the right is evaluated and assigned to x
  • Conditions: To check if an expression evaluates to true or false.
if (x > 0) { ... }  // Condition checks if expression evaluates to true
  • Function arguments: To pass values to functions.
print(x + y); // Expression is evaluated and passed as argument
  • Return values: To return a value from a function.
int sum(int x, int y) {
  return x + y;  // Expression is evaluated and returned
}

Expressions allow you to:

  • Perform calculations and manipulate data.

  • Make decisions in conditions and loops.

  • Pass values to and from functions.

The main uses of expressions are:

  • Performing calculations quickly and concisely.

  • Making code more readable by assigning meaningful names to subexpressions.

  • Allowing code reusability by evaluating an expression once and using its result multiple times.


Expression Type

Expressions produce a result of a specific type, which we call the expression's implicit type. This allows type-checking of expressions when they are used in statements.

For example, consider the expression:

5 + 6

This expression evaluates to 11, which is an integer value. So the implicit type of this expression is int.

This implicit type is used for type-checking when the expression is used in a statement. For example:

int x = 5 + 6;  // Ok, implicit int type matches x's type
string y = 5 + 6; // Error, implicit int type does not match string type

Here, the first assignment is valid since the expression's implicit int type matches the type of x, which is also int.

But the second assignment results in a type mismatch error, since the expression's int type does not match the string type of y.

So in summary:

  • Expressions have an implicit type based on the types of their operands and operators.

  • This implicit type is used for type-checking when the expression is used in statements.

  • Type mismatches between an expression's implicit type and a variable's type will result in a compiler error.

This type-checking helps catch errors at compile-time, rather than letting type mismatches cause runtime issues.


Operators

C# has several types of operators depending on the expression types:

Arithmetic Operators:

  • Used on numeric types (int, float, double):
+    // Addition   
-    // Subtraction
*    // Multiplication  
/    // Division  
%    // Modulus

Relational Operators:

  • Used on any type to compare values:
==  // Equal to
!=  // Not equal to
>   // Greater than
<   // Less than 
>=  // Greater than or equal to  
<=  // Less than or equal to

Logical Operators:

  • Used on bool operands:
&&  // Logical AND
||  // Logical OR
!   // Logical NOT

Assignment Operators:

  • Used to assign values to variables:
=     // Simple assignment 
+=    // Add and assign
-=    // Subtract and assign
*=    // Multiply and assign
/=    // Divide and assign
%=    // Modulus and assign

Conditional Operators:

  • Used to assign a value based on a condition:
condition ? true_value : false_value

Bitwise Operators:

  • Used on integral types:
&   // Bitwise AND
|   // Bitwise OR
^   // Bitwise XOR
~   // Bitwise complement  
<<  // Left shift 
>>  // Right shift

So in summary, C# has different types of operators depending on the expression types - arithmetic for numbers, relational for comparisons, logical for bools, assignment, conditional and bitwise. The operands and result type depend on the specific operator.


Priority

C# uses infix expressions for most operators, meaning the operator appears between the two operands. For example:

a + b   // Addition 
a == b  // Equality
a && b  // Logical AND

For complex expressions with multiple operators, C# follows the standard order of operations:

  1. Parentheses

  2. Exponentiation

  3. Multiplication and Division

  4. Addition and Subtraction

For operators with the same priority, they are evaluated from left to right.

Round parentheses can be used to explicitly define the order of evaluation, overriding the standard order of operations. For example:

(a + b) * c  // Adds a and b first, then multiplies by c
a + (b * c)  // Multiplies b and c first, then adds to a

Parentheses are especially useful when the standard order of operations would yield an unintended result.

So in summary:

  • C# uses infix expressions for most operators

  • It follows a standard order of operations

  • Round parentheses can be used to override the standard order

  • They explicitly group expressions to define the order of evaluation


Casting

Casting in C# refers to converting a value from one data type to another. There are two types of casting:

  1. Implicit casting - Converting from a smaller type to a larger type size. This is done automatically by the compiler and does not require any explicit casting syntax.

For example:

int i = 10;
long l = i;  // Implicit cast from int to long
  1. Explicit casting - Converting from a larger type to a smaller type size. This requires using explicit cast syntax.

For example:

long l = 100;
int i = (int)l;  // Explicit cast from long to int

Here we use the (int) cast to convert the long value to an int.

It is important to know about casting for a few reasons:

  1. It allows the combining of values of different types in expressions.

  2. It can avoid errors when converting between incompatible types. The explicit cast syntax makes it clear that a type conversion is intended.

  3. It can cause data loss when converting to a smaller type. The explicit cast syntax makes the developer aware of this.

  4. It is required when passing arguments to methods/functions that expect a specific type.

  5. It can improve performance by avoiding unnecessary object creations through implicit boxing/unboxing.

So in summary, casting allows converting values between incompatible types in C#. Implicit casts are automatic, while explicit casts require syntax. Explicit casts make the developer aware of potential data loss or conversion issues.


Disclaim: There are many other thigs to say about Variables, DataTypes and Expressions, but for now we can continue with this minimum knowledge and understand statements. In next articles we will continue using AI to explain how expressions are used in statements.