Here are notes about the topics we covered in lecture 3. For more details on anything below, see the Essential C# textbook or the C# reference pages.
Strings may normally contain the escape sequences described above.
But you may prefix a string with @
to create a verbatim
string in which the backslash is an ordinary character. A
verbatim string may even contain newlines:
WriteLine(@"\one\ \two\ \three\" );
writes
\one\ \two\ \three\
A interpolated value may be followed by a format specifier (preceded by a colon).
There are many predefined format specifiers. Many format specifiers can be followed by an integer called the precision, whose meaning varies among specifiers. Here are a few of the most useful:
d
– prints a value of integral type, padding
zeros to the left. The precision is the minimum number of digits to
print.
f
– prints a number in fixed-point decimal
(i.e. not using scientific notation). The precision is the number of
the digits after the decimal point.
n
– prints a number using thousands
separators. The precision is the number of digits after the decimal
point.
For example,
const int i = 1357; const double pi = 3.14159; WriteLine($"{i:d6} {pi:f2} {i:n0}");
writes
001357 3.14 1,357
The conditional operator (? :
) is similar to
the if
statement, but it is an expression, not a
statement. It takes a Boolean value and two extra values. It returns
the first of these values if the boolean is true, or the second if it
is false. For example, the following statement computes the greater
of i and j and assigns it to k:
int i, j; ... int k = (i > j ? i : j);
A parameter
marked with ref
is passed by reference: the method can modify the variable that is
passed. Here's a method that swaps two variables:
static void swap(ref int a, ref int b) { int t = a; a = b; b = t; }
You must include the keyword ref
when passing an
argument by reference:
int i = 3, j = 4; swap(ref i, ref j);
A parameter marked with out
returns a value to the caller. This method takes two integers and
returns both their sum and product:
static void sumAndProduct(int a, int b, out int sum, out int product) { sum = a + b; product = a * b; }
You must include the keyword out
when passing a variable
to an out
parameter:
int s, p; sumAndProduct(3, 4, out s, out p);
You can declare a new variable as you invoke a method with an out
parameter. The following is equivalent to the two preceding lines:
sumAndProduct(3, 4, out int s, out int p);
If the last parameter to a method is marked with params
and has type T[], then in its place the method can receive any number
of arguments of type T. The caller may pass individual values
separated by commas, or may pass an array of type T[].
For example, this method receives a parameter array of integers and returns their sum:
static int sum(params int[] a) { int s = 0; foreach (int i in a) s += i; return s; }
It can be invoked as
int s = sum(4, 5, 6);
Alternatively, the caller can pass an array:
int[] a = { 4, 5, 6 }; int s = sum(a);
You may declare multiple methods that have the same name but have different numbers and/or types of parameters. This is called method overloading. For example:
static int more(int i) => i + 1 static int more(short s) => s + 2 static string more(string s) => s + " "
When calling an overloaded method, sometimes there is more than one candidate method. For example, consider this method call:
byte b = 77; WriteLine(more(b));
Both of the first two method declarations above are candidates for
this call, since byte
is implicitly convertible to both
int
and short
. In this situation, C# will
favor the overload that involves converting to a more specific
type. short
is more specific than int
, so
in the example above C# will call the method
int more(short s)
and will write the value 79.
For any types T and U, C# considers T to be more specific than U if there is an implicit conversion from T to U, but none from to U.
Every type in C# is either a value type or a reference type.
value types: all numeric types, bool
, char
reference types: string
, arrays, classes
When a variable's type is a value type, the variable holds a value. An assignment between variables of value type copies the value from one variable to another.
When a variable's type is a reference type, the variable holds a pointer to an object. An assignment between variables of reference type makes them point to the same object.
For example:
int[] a = { 4, 5, 6 }; int[] b = a; // now b and a point to the same array a[1] = 7; WriteLine(b[1]); // writes 7
Any variable of reference type may hold the special value null
.
Note especially that null
is not the same as the empty string.
A class is an abstract data type that can contain fields, methods, and other kinds of members.
Here is a definition for a simple class representing a point in two dimensions. It has two fields, one constructor and two methods:
using static System.Math; class Point { double x, y; public Point(double x, double y) { this.x = x; this.y = y; } public void move(double dx, double dy) { x += dx; y += dy; } public double distanceFromOrigin() { return Sqrt(x * x + y * y); } }
this
is a special value that refers to the object on
which a method, constructor or other member was invoked.
Every member in a class can be either public
or private
.
(There are additional access levels that we will learn about soon.)
public
members are visible outside the class; private
members can be used only within the class.
The default access level is private
.
A constructor makes a new instance of a class. It always has the same name as its containing class.
To call a constructor, use the new
operator and pass any required arguments:
Point p = new Point(3.0, 4.0);
If a class definition includes no constructors, then C# provides a default constructor that takes no arguments.
Constructors may be overloaded. A constructor may call another constructor; this is called constructor chaining. For example, we could add a second constructor to the Point class that chains to the constructor with two parameters:
public Point(double x) : this(x, 0.0) { }
For any class, you may define a ToString
method that
converts an instance of the class to a string. For example:
public override string ToString() => $"({x}, {y})";
(We will learn more about override
when we discuss
inheritance in an upcoming lecture.)