Operators
Operators combine values into new values — arithmetic, comparisons, and boolean logic. Most of them behave exactly like you'd expect from math class. One of them, integer division, trips up almost everyone the first time they hit it.
Arithmetic operators
C# gives you +, -, *, /, and % (remainder). The one to watch closely is division: when both operands are integers, C# performs integer division and throws away anything after the decimal point — it doesn't round, it truncates:
int a = 7; int b = 2; Console.WriteLine(a / b); Console.WriteLine(a % b); Console.WriteLine((double)a / b);
3 1 3.5
7 / 2 gives 3, not 3.5, because both sides are int. 7 % 2 gives the remainder, 1. To get the precise answer, at least one side of the division needs to be a floating-point type — the (double) in front of a is a cast, forcing that specific value to be treated as a double before the division happens.
Comparison operators
<, >, <=, >=, ==, and != all produce a bool:
int x = 10; int y = 20; Console.WriteLine(x < y); Console.WriteLine(x == y); Console.WriteLine(x != y);
True False True
A detail worth remembering: = assigns a value, == compares two values. Mixing them up in other C-family languages can silently compile into a bug; in C#, writing x = y where a condition is expected usually won't even compile unless x and y are both bool, which saves you from that particular trap most of the time.
Logical operators
&& (and), || (or), and ! (not) combine or invert boolean values. && and || are also short-circuiting: if the left side of && is already false, C# never bothers evaluating the right side, since the answer can't change:
int age = 25; bool hasLicense = true; Console.WriteLine(age >= 18 && hasLicense); Console.WriteLine(age < 18 || !hasLicense);
True False
Compound assignment
Updating a variable based on its own current value is common enough that C# gives it shorthand: total += 5 means total = total + 5. The same pattern exists for -=, *=, /=, and the increment/decrement operators ++ and --.
int variables expecting a fractional answer and get a suspiciously round number back, integer division is almost always the cause. Cast one operand to double (or declare it as double in the first place) before the division happens, not after.