What the ! operator does
The logical not operator, written !, flips a boolean value: true becomes false and false becomes true. It goes in front of the value it flips, and it takes only one operand, unlike || and &&, which take two.
Console.WriteLine(!true); // False
Console.WriteLine(!false); // True
Console.WriteLine(7 <= 10); // True
Console.WriteLine(!(7 <= 10)); // False
Console.WriteLine(12 != 12); // False
Console.WriteLine(!(12 != 12)); // True
C# prints booleans with a capital first letter, True and False.
Why the parentheses
! binds very tightly. It applies to the single value right after it, not to a whole comparison. !7 <= 10 would try to flip the number 7, which makes no sense, so the code doesn't compile. Wrapping the comparison in parentheses, as in !(7 <= 10), flips the result of the comparison.
Using ! with boolean variables
The most common use is on a bool variable, where it reads like "if not":
bool hungry = true;
if (!hungry) {
Console.WriteLine("I can wait a little longer");
} else {
Console.WriteLine("I need food!");
}
Here hungry is true, so !hungry is false. The if branch is skipped, the else runs, and the output is I need food!.
Notice that you don't write hungry == false or hungry == true. A bool is already a condition, so if (hungry) and if (!hungry) are the clearest forms.
Flipping a combined condition
You can put ! in front of a parenthesised group. !(a || b) is true only when both a and b are false. The same reasoning gives a handy pair of equivalences, known as De Morgan's laws:
!(a || b)is the same as!a && !b.!(a && b)is the same as!a || !b.
Pick the form that reads more clearly for the condition at hand.
Naming and readability
A boolean variable should be named so that ! in front of it reads naturally. if (!isLoggedIn) reads as "if not logged in", which is easy to follow. A condition with several negations is harder: !(a < b) means the same as a >= b, and the second form is usually easier to read. Use ! when it makes the condition shorter or clearer, not as a habit.
The precise rule for comparisons is that the opposite of < is >=, the opposite of <= is >, and the opposite of == is !=. For whole numbers, that is exactly right. Values that aren't numbers in the ordinary sense, such as double.NaN, break the first two rules, but you won't meet them in this lesson.
Like any boolean expression, a negation can be stored: bool isNight = !isDaytime; gives you a new variable that always holds the opposite of isDaytime at the moment of the assignment.
Common mistakes with !
- Confusing
!with!=.!flips a boolean.!=compares two values and means "not equal". Both are valid, so!(x == 3)andx != 3are the same condition. - Forgetting the parentheses.
!x == 3tries to apply!toxalone. Ifxis anint, this is a compile error. Write!(x == 3)or, better,x != 3. - Using
!on something that isn't a bool. C# is strict here. Unlike some other languages, it doesn't treat numbers or strings as true or false, so!countfails to compile whencountis anint. Compare it instead:count == 0. - Double negatives.
!!flagis justflag, and a variable namednotReadyused as!notReadyis hard to read. Name booleans positively, such asisReady.
The exercise, step by step
The code gives you one variable, bool isSunny = true;. The goal is to print one message when it isn't sunny and another when it is.
- Test the negation. Write
if (!isSunny)and print"Learning to code"inside it. The block runs whenisSunnyisfalse. - Add the
else. Write} else {on the line that closes theifblock, and print"Going to the beach". It runs in every other case, which here meansisSunnyistrue.
bool isSunny = true;
if (!isSunny) {
Console.WriteLine("Learning to code");
} else {
Console.WriteLine("Going to the beach");
}
Because isSunny starts as true, !isSunny is false and the program prints:
Going to the beach
Set isSunny to false and the output becomes Learning to code.
Key takeaways
!turnstrueintofalseandfalseintotrue.- It applies to the value right after it, so wrap comparisons in parentheses:
!(a < b). - In C#,
!works only onboolvalues. - Prefer
if (!flag)overif (flag == false).