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.
The following table shows a set of operators used in the
C# language.
Category
Symbol
Sign
operators + -
Arithmetic + - * / %
Logical
(boolean and bitwise) &
| ^ ! ~ && || true false
String
concatenation +
Increment,
decrement ++ --
Shift <<
>>
Relational ==
!= < > <= >=
Assignment = += -= *= /= %= &= |= ^=
<<= >>=
Member
access .
Indexing []
Cast ()
Ternary ?:
Delegate
concatenation and removal +
-
Object
creation new
Type
information as is sizeof
typeof
Overflow
exception control checked
unchecked
Indirection
and address *
-> [] &
Lambda =>
|
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.
Sign operators
There are two sign operators. + and -. They are used to
indicate or change the sign of a value.
using
System;
public
class SignOperator
{
static void Main()
{
Console.WriteLine(2);
Console.WriteLine(+2);
Console.WriteLine(-2);
}
}
|
+ 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.
using
System;
public
class MinusSign
{
static void Main()
{
int a = 1;
Console.WriteLine(-a); // prints -1
Console.WriteLine(-(-a)); // prints 1
}
}
|
The minus sign changes the sign of a value.
The 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.
int x = 1;
Here we assign a number to the x variable.
x = x + 1;
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.
3 = x;
This code example results in syntax error. We cannot
assign a value to a literal.
Concatenating strings
The + operator is also used to concatenate strings.
using
System;
public
class Concatenate
{
static void Main()
{
Console.WriteLine("Return "
+ "of " + "the king.");
}
}
|
We join three strings together using string
concatenation operator.
$ ./catstrings.exe
Return of the king.
This is the outcome of the catstrings.exe program.
Increment, decrement operators
Incrementing or decrementing a value by one is a common
task in programming. C# has two convenient operators for this. ++ and --.
x++;
x = x + 1;
...
y--;
y = y - 1;
The above two pairs of expressions do the same.
using
System;
public
class IncrementDecrement
{
static void Main()
{
int x = 6;
x++;
x++;
Console.WriteLine(x);
x--;
Console.WriteLine(x);
}
}
|
In the above example, we demonstrate the usage of both
operators.
int x = 6;
x++;
x++;
We initiate the x variable to 6. Then we increment the x
two times. Now the variable equals to 8.
x--;
We use the decrement operator. Now the variable equals
to 7.
$ ./incdec.exe
8
7
And here is the output of the example.
Arithmetic operators
The following is a table of arithmetic operators in C#.
Symbol Name
+ Addition
- Subtraction
* Multiplication
/ Division
% Remainder
The following example shows arithmetic operations.
using
System;
public
class Arithmetic
{
static void Main()
{
int a = 10;
int b = 11;
int c = 12;
int add = a + b + c;
int sb = c - a;
int mult = a * b;
int div = c / 3;
int rem = c % a;
Console.WriteLine(add);
Console.WriteLine(sb);
Console.WriteLine(mult);
Console.WriteLine(div);
Console.WriteLine(rem);
}
}
|
In the preceding example, we use addition, subtraction,
multiplication, division and remainder operations. This is all familiar from
the mathematics.
int rem = c % a;
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.
$ ./arithmetic.exe
33
2
110
4
2
This is the output of the example.
Next we will show the distinction between integer and
floating point division.
using
System;
public
class Division
{
static void Main()
{
int c = 5 / 2;
Console.WriteLine(c);
double d = 5 / 2.0;
Console.WriteLine(d);
}
}
|
In the preceding example, we divide two numbers.
int c = 5 / 2;
Console.WriteLine(c);
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.
double d = 5 / 2.0;
Console.WriteLine(d);
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.
$ ./division.exe
2
2.5
We see the result of the division.exe program.
Boolean operators
In C#, we have three logical operators. The bool keyword
is used to declare a Boolean value.
Symbol Name
&& logical
and
|| logical
or
! negation
Boolean operators are also called logical.
using
System;
public
class BooleanOperators
{
static void Main()
{
int x = 3;
int y = 8;
Console.WriteLine(x == y);
Console.WriteLine(y > x);
if (y > x)
{
Console.WriteLine("y is
greater than x");
}
}
}
|
Many expressions result in a boolean value. Boolean
values are used in conditional statements.
Console.WriteLine(x == y);
Console.WriteLine(y > x);
Relational operators always result in a boolean value.
These two lines print false and true.
if (y > x)
{
Console.WriteLine("y is greater than x");
}
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#.
using
System;
public
class AndOperator
{
static void Main()
{
bool a = true && true;
bool b = true && false;
bool c = false && true;
bool d = false && false;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
}
}
|
Example shows the logical and operator. It evaluates to
true only if both operands are true.
$ ./andoperator.exe
True
False
False
False
Only one expression results in true.
The logical or || operator evaluates to true, if either
of the operands is true.
using
System;
public
class OrOperator
{
static void Main()
{
bool a = true || true;
bool b = true || false;
bool c = false || true;
bool d = false || false;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
}
}
|
If one of the sides of the operator is true, the outcome
of the operation is true.
$ ./orop.exe
True
True
True
False
Three of four expressions result in true.
The negation operator ! makes true false and false true.
using
System;
public
class Negation
{
static void Main()
{
Console.WriteLine(! true);
Console.WriteLine(! false);
Console.WriteLine(! (4 < 3));
}
}
|
The example shows the negation operator in action.
$ ./negation.exe
False
True
True
This is the output of the negation.exe program.
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.
using
System;
public
class ShortCircuit
{
static void Main()
{
Console.WriteLine("Short
circuit");
if (One() && Two())
{
Console.WriteLine("Pass");
}
Console.WriteLine("#############");
if (Two() || One())
{
Console.WriteLine("Pass");
}
}
public static bool One()
{
Console.WriteLine("Inside
one");
return false;
}
public static bool Two()
{
Console.WriteLine("Inside
two");
return true;
}
}
|
We have two methods in the example. They are used as
operands in boolean expressions. We will see if they are called or not.
if (One() && Two())
{
Console.WriteLine("Pass");
}
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.
Console.WriteLine("#############");
if (Two() || One())
{
Console.WriteLine("Pass");
}
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.
$ ./shortcircuit.exe
Short circuit
Inside one
#############
Inside two
Pass
We see the result of the shorcircuit.exe program.
Relational Operators
Relational operators are used to compare values. These
operators always result in boolean value.
Symbol Meaning
< less
than
<= less
than or equal to
> greater
than
>= greater
than or equal to
== equal
to
!= not
equal to
Relational operators are also called comparison
operators.
using
System;
public
class Relational
{
static void Main()
{
Console.WriteLine(3 < 4);
Console.WriteLine(3 == 4);
Console.WriteLine(4 >= 3);
Console.WriteLine(4 != 3);
}
}
|
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 the == to compare numbers. Some languages
like Ada, Visual Basic, or Pascal use = for comparing numbers.
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#.
Symbol Meaning
~ bitwise
negation
^ bitwise
exclusive or
& bitwise
and
| bitwise
or
The bitwise negation operator changes each 1 to 0 and 0
to 1.
Console.WriteLine(~ 7); // prints -8
Console.WriteLine(~ -8); // prints 7
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.
00110
& 00011
= 00010
The first number is a binary notation of 6. The second
is 3. The result is 2.
Console.WriteLine(6 & 3); // prints 2
Console.WriteLine(3 & 6); // prints 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.
00110
| 00011
= 00111
The result is 00110 or decimal 7.
Console.WriteLine(6 | 3); // prints 7
Console.WriteLine(3 | 6); // prints 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.
00110
^ 00011
= 00101
The result is 00101 or decimal 5.
Console.WriteLine(6 ^ 3); // prints 5
Console.WriteLine(3 ^ 6); // prints 5
Compound assignment operators
The compound assignment operators consist of two
operators. They are shorthand operators.
a = a + 3;
a += 3;
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:
-= *= /=
%= &= |=
<<= >>=
using
System;
public
class CompoundOperators
{
static void Main()
{
int a = 1;
a = a + 1;
Console.WriteLine(a);
a += 5;
Console.WriteLine(a);
a *= 3;
Console.WriteLine(a);
}
}
|
In the example, we use two compound operators.
int a = 1;
a = a + 1;
The a variable is initiated to one. 1 is added to the
variable using the non-shorthand notation.
a += 5;
Using a += compound operator, we add 5 to the a
variable. The statement is equal to a = a + 5;.
a *= 3;
Using the *= operator, the a is multiplied by 3. The
statement is equal to a = a * 3;.
$ ./compoundoperators.exe
2
7
21
This is the example output.
Type information
Now we will 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.
using
System;
public
class SizeType
{
static void Main()
{
Console.WriteLine(sizeof(int));
Console.WriteLine(sizeof(float));
Console.WriteLine(sizeof(Int32));
Console.WriteLine(typeof(int));
Console.WriteLine(typeof(float));
}
}
|
We use the sizeof and typeof operators.
$ ./sizetype.exe
4
4
4
System.Int32
System.Single
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.
using
System;
class
Base {}
class
Derived : Base {}
public
class IsOperator
{
static void Main()
{
Base _base = new Base();
Derived derived = new Derived();
Console.WriteLine(_base is Base);
Console.WriteLine(_base is Object);
Console.WriteLine(derived is Base);
Console.WriteLine(_base is Derived);
}
}
|
We create two objects from user defined types.
class Base {}
class Derived : Base {}
We have a Base and a Derived class. The Derived class
inherits from the Base class.
Console.WriteLine(_base is Base);
Console.WriteLine(_base is Object);
Base equals Base and so the first line print True. A
Base is also compatible with Object type. This is because each class inherits
from the mother of all classes — the Object class.
Console.WriteLine(derived is Base);
Console.WriteLine(_base is Derived);
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.
$ ./isoperator.exe
True
True
True
False
This is the output of example.
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.
using
System;
class
Base {}
class
Derived : Base {}
public
class AsOperator
{
static void Main()
{
object[] objects = new object[6];
objects[0] = new Base();
objects[1] = new Derived();
objects[2] = "ZetCode";
objects[3] = 12;
objects[4] = 1.4;
objects[5] = null;
for (int i=0; i<objects.Length;
++i)
{
string s = objects[i] as string;
Console.Write ("{0}:",
i);
if (s != null)
Console.WriteLine (s);
else
Console.WriteLine ("not
a string");
}
}
}
|
In the above example, we use the as operator to perform
casting.
string s = objects[i] as string;
We try to cast various types to the string type. But only
once the casting is valid.
$ ./asoperator.exe
0:not a string
1:not a string
2:ZetCode
3:not a string
4:not a string
5:not a string
This is the output of the example.
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?
3 + 5 * 5
Like in mathematics, the multiplication operator has a
higher precedence than addition operator. So the outcome is 28.
(3 + 5) * 5
To change the order of evaluation, we can use
parentheses. Expressions inside parentheses are always evaluated first.
The 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.
using
System;
public
class CSharpApp
{
static void Main()
{
int? x = null;
int? y = null;
int z = x ?? y ?? -1;
Console.WriteLine(z);
}
}
|
An example program for null-coalescing operator.
int? x = null;
int? y = null;
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.
int z = x ?? y ?? -1;
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, y variables are null, we assign -1 to z.
$ ./nullcoalescing.exe
-1
This is the output of program.
The 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.
cond-exp ? exp1 : exp2
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.
using
System;
public
class CSharpApp
{
static void Main()
{
int age = 31;
bool adult = age >= 18 ? true :
false;
Console.WriteLine("Adult:
{0}", adult);
}
}
|
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.
bool adult = age >= 18 ? true : false;
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.
$ ./ternary.exe
Adult: True
A 31 years old person is adult.
The 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.
using
System;
using
System.Collections.Generic;
public
class LambdaOperator
{
static void Main()
{
List<int> list = new
List<int>()
{ 3, 2, 1, 8, 6, 4, 7, 9, 5 };
List<int> sublist =
list.FindAll(val => val > 3);
foreach (int i in sublist)
{
Console.WriteLine(i);
}
}
}
|
We have a list of integer numbers. We print all numbers
that are greater than 3.
List<int> list = new List<int>()
{ 3, 2, 1, 8,
6, 4, 7, 9, 5 };
We have a generic list of integers.
List<int> sublist = list.FindAll(val => val
> 3);
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.
foreach (int i in sublist)
{
Console.WriteLine(i);
}
The items of the sublist collection are printed to the
terminal.
$ ./lambda.exe
8
6
4
7
9
5
Values from the list of integers that are greater than
3.