• Shuffle
    Toggle On
    Toggle Off
  • Alphabetize
    Toggle On
    Toggle Off
  • Front First
    Toggle On
    Toggle Off
  • Both Sides
    Toggle On
    Toggle Off
  • Read
    Toggle On
    Toggle Off
Reading...
Front

Card Range To Study

through

image

Play button

image

Play button

image

Progress

1/145

Click to flip

Use LEFT and RIGHT arrow keys to navigate between flashcards;

Use UP and DOWN arrow keys to flip the card;

H to show hint;

A reads text to speech;

145 Cards in this Set

  • Front
  • Back

chief architect of the language

Anders Hejlsberg

Unified type system

The fundamental building block in C# is an encapsulated unit of data and functions called a type. C# has a unified type system, where all types ultimately share a common base type. This means that all types, whether they represent business objects or are primitive types such as numbers, share the same basic
set of functionality. For example, an instance of any type can be converted to a string by calling its ToString method

Interface in C#

An interface is like a class, except that it only describes members. The implementation for
those members comes from types that implement the interface. Interfaces are particularly useful in scenarios where multiple inheritance is required

Properties, methods, and events

In C#, methods are only one kind of function member, which also includes properties and events (there are others, too). Properties are function members that encapsulate a piece of an object’s state, such as a button’s color or a label’s text. Events are function members that simplify acting on object state changes.

C# is primarily a type-safe language, meaning

C# is primarily a type-safe language, meaning that instances of types can interact only through protocols they define, thereby ensuring each type’s internal consistency.
For instance, C# prevents you from interacting with a string type as though it were an integer type.



More specifically, C# supports static typing, meaning that the language enforces type safety at compile time. This is in addition to type safety being enforced at runtime.

static typing

meaning that the language enforces type safety at compile time.

C# is also called a strongly typed language because

its type rules (whether enforced statically or at runtime) are very strict. For instance, you cannot call a function that’s designed to accept an integer with a floating-point number, unless you first explicitly convert the floating-point number to an integer. This helps prevent mistakes

C# code may run on a runtime other than the Microsoft Common Language Runtime. The most notable example is the

Mono project, which has its own
C# compiler and runtime, running on Linux, Solaris, Mac OS X, and Windows

.NET Framework consists of



WinRT

.NET Framework consists of CLR plus a vast set of libraries.



WinRT - Windows Runtime

WinRT

WinRT is an execution interface and runtime environment for accessing libraries in a languageneutral and object-oriented fashion. It ships with Windows 8 and is (in part) an enhanced version of Microsoft’s Component Object Model or COM

reference assembly

exists purely to compile against and may
have a restricted set of types and members. This allows developers to install the full .NET Framework on their machines while coding certain projects as though they had only a subset. The actual functionality comes at runtime from assemblies in the Global Assembly Cache which may superset
the reference assemblies.

C# 5.0’s big new feature is

support for asynchronous functions via two new keywords, async and await. Asynchronous functions enable asynchronous continuations,
which make it easier to write responsive and thread-safe rich-client applications. They also make it easy to write highly concurrent and efficient I/O-bound applications that don’t tie up a thread resource per operation.

What’s New in C# 4.0

• Dynamic binding
• Optional parameters and named arguments
• Type variance with generic interfaces and delegates
• COM interoperability improvements

Dynamic binding

Dynamic binding defers binding—the process of resolving types and members—from compile time to runtime and is useful in scenarios that would otherwise require complicated reflection code. Dynamic binding is also useful when interoperating with dynamic languages and COM components.

Optional parameters

Optional parameters allow functions to specify default parameter values so that callers can omit arguments and named arguments allow a function caller to identify an argument by name rather than position.

Type variance

Type variance rules were relaxed in C# 4.0 4), such that type parameters in generic interfaces and generic delegates can be marked as covariant or contravariant, allowing more natural type conversions

COM interoperability

COM interoperability was enhanced in C# 4.0 in three ways


First, arguments can be passed by reference without the ref keyword (particularly useful
in conjunction with optional parameters).



Second, assemblies that contain COM
interop types can be linked rather than referenced. Linked interop types support type
equivalence, avoiding the need for Primary Interop Assemblies and putting an end
to versioning and deployment headaches.



Third, functions that return COM-Variant
types from linked interop types are mapped to dynamic rather than object, eliminating
the need for casting.

Implicitly typed local variables

let you omit the variable type in a declaration statement, allowing the compiler to infer it. This reduces clutter as well as allowing anonymous types 4), which are simple classes created on the fly that are commonly used in the final output of LINQ queries. Arrays can also be implicitly typed

Object initializers

simplify object construction by allowing properties to be set inline after the constructor call. Object initializers work with both named and anonymous types.



public class Bunny {
public string Name;
public bool LikesCarrots;
public bool LikesHumans;
public Bunny () {}
public Bunny (string n) { Name = n; }
}
Using object initializers, you can instantiate Bunny objects as follows:
// Note parameterless constructors can omit empty parentheses



Bunny b1 = new Bunny { Name="Bo", LikesCarrots=true, LikesHumans=false };
Bunny b2 = new Bunny ("Bo") { LikesCarrots=true, LikesHumans=false };

Lambda expressions

are miniature functions created by the compiler on the fly, and are particularly useful in “fluent” LINQ queries

Extension methods

Extension methods extend an existing type with new methods (without altering the type’s definition), making static methods feel like instance methods. LINQ’s query operators are implemented as extension methods.

Query expressions

provide a higher-level syntax for writing LINQ queries that can be substantially simpler when working with multiple sequences or range
variables.

Expression trees

are miniature code DOMs (Document Object Models) that describe lambda expressions assigned to the special type Expressiongate>. Expression trees make it possible for LINQ queries to execute remotely because they can be introspected and translated at runtime

Automatic properties

Automatic properties cut the work in writing properties that simply get/set a private backing field by having the compiler do that work automatically

Partial `methods

Partial methods let an auto-generated partial class provide customizable hooks for manual authoring which “melt away” if unused.



partial class PaymentForm // In auto-generated file {
...
partial void ValidatePayment (decimal amount);
}
partial class PaymentForm // In hand-authored file {
...
partial void ValidatePayment (decimal amount) {
if (amount > 100)
...
}
}

C# compiler compiles source code

C# compiler compiles source code, specified as a set of files with the .cs extension, into an assembly. An assembly is the unit of packaging and deployment in .NET. An assembly can be either an application or a library. A normal console or Windows application has a Main method and is an .exe file. A library is a .dll and is equivalent to an .exe without an entry point. Its purpose is to be called upon (referenced)
by an application or by other libraries. The .NET Framework is a set of libraries.

If you really want to use an identifier that clashes with a keyword, you can do so by qualifying it with

the @ prefix. For instance:
class class {...} // Illegal
class @class {...} // Legal



The @ symbol doesn’t form part of the identifier itself. So @myVariable is the same as dmyVariable.

Data members and function members that don’t operate on the instance of the type, but rather on the type itself, must be marked as

static. The Test.Main and Console.WriteLine methods are static methods.

Implicit conversions are allowed when both of the following are true

The compiler can guarantee they will always succeed.
No information is lost in conversion.

explicit conversions are required when one of the following is true

The compiler cannot guarantee they will always succeed.
Information may be lost during conversion

All C# types fall into the following categories

Value types - most built in type


Reference types
Generic type parameters
Pointer types

checked operator

checked operator tells the runtime to generate an OverflowException rather than overflowing silently when an integral expression or statement exceeds the arithmetic limits of that type.



int a = 1000000;
int b = 1000000;
int c = checked (a * b); // Checks just the expression.
checked // Checks all expressions
{ // in statement block.
...
c = a * b;
...
}

unchecked operator

If you then need to disable overflow checking just for specific expressions or statements, you can do so with the unchecked operator. For example, the following code will not throw exceptions—even if compiled with /checked+:
int x = int.MaxValue;
int y = unchecked (x + 1);
unchecked { int z = x + 1; }
Numeric

short x = 1, y = 1;
short z = x + y; // Compile-time error why

In this case, x and y are implicitly converted to int so that the addition can be performed. This means the result is also an int, which cannot be implicitly cast back to a short (because it could cause loss of data)



The 8- and 16-bit integral types are byte, sbyte, short, and ushort. These types lack their own arithmetic operators, so C# implicitly converts them to larger types as required.

Special Float and Double Values

Unlike integral types, floating-point types have values that certain operations treat specially. These special values are NaN (Not a Number), +∞, −∞, and −0.

Dividing a nonzero number by zero results in an infinite value. For example:


Console.WriteLine ( 1.0 / 0.0); // ?


Console.WriteLine ( -1.0 / 0.0); // ?


Console.WriteLine ( 1.0 / -0.0); // ?


Console.WriteLine ( -1.0 / -0.0); // ?

Console.WriteLine ( 1.0 / 0.0); // Infinity
Console.WriteLine (−1.0 / 0.0); // -Infinity
Console.WriteLine ( 1.0 / −0.0); // -Infinity
Console.WriteLine (−1.0 / −0.0); // Infinity

Dividing zero by zero, or subtracting infinity from infinity, results in a NaN. For example:



Console.WriteLine ( 0.0 / 0.0); //??


Console.WriteLine ((1.0 / 0.0) − (1.0 / 0.0)); // ??

Console.WriteLine ( 0.0 / 0.0); // NaN
Console.WriteLine ((1.0 / 0.0) − (1.0 / 0.0)); // NaN

When using ==, a NaN value is _______________ ?

When using ==, a NaN value is never equal to another value, even another NaN value:
Console.WriteLine (0.0 / 0.0 == double.NaN); // False
To test whether a value is NaN, you must use the float.IsNaN or double.IsNaN method:
Console.WriteLine (double.IsNaN (0.0 / 0.0)); // True

When using object.Equals two NaN values are ___________

equal:
Console.WriteLine (object.Equals (0.0 / 0.0, double.NaN)); // True

double Versus decimal

double is useful for scientific computations (such as computing spatial coordinates). decimal is useful for financial computations and values that are “man-made” rather than the result of real-world measurements.

conditional operator def

q ? a : b



static int Max (int a, int b)
{
return (a > b) ? a : b;
}


Arrays

char[] vowels = new char[5]; // Declare an array of 5 characters

array initialization expression

array initialization expression lets you declare and populate an array in a single step:



char[] vowels = new char[] {'a','e','i','o','u'};



or simply:
char[] vowels = {'a','e','i','o','u'};

Multidimensional arrays come in two varieties

rectangular - int[,] matrix = new int[3,3];


jagged - int[][] matrix = new int[3][];


// for jagged array


for (int i = 0; i < matrix.Length; i++)
{
matrix[i] = new int[3]; // Create inner array
for (int j = 0; j < matrix[i].Length; j++)
matrix[i][j] = i * 3 + j;
}

static void Main()
{
int x;
Console.WriteLine (x); // Compile-time error why
}

Local variables must be assigned a value before they can be read.



Fields and array elements are automatically initialized with the default values for their type. The following code outputs 0, because array elements are implicitly assigned to their default values.

By default, arguments in C# are passed by

value



This means a copy of the value is created when passed to the method

The ref modifier

To pass by reference, C# provides the ref parameter modifier.



class Test {
static void Swap (ref string a, ref string b) {
string temp = a;
a = b;
b = temp;
}
static void Main() {
string x = "Penn";
string y = "Teller";
Swap (ref x, ref y);
Console.WriteLine (x); // Teller
Console.WriteLine (y); // Penn
} }

The out modifier

An out argument is like a ref argument, except it:
• Need not be assigned before going into the function
• Must be assigned before it comes out of the function
The out modifier is most commonly used to get multiple return values back from a method.



class Test {
static void Split (string name, out string firstNames,
out string lastName) {
int i = name.LastIndexOf (' ');
firstNames = name.Substring (0, i);


lastName = name.Substring (i + 1);
}
static void Main() {
string a, b;
Split ("Stevie Ray Vaughan", out a, out b);
Console.WriteLine (a); // Stevie Ray
Console.WriteLine (b); // Vaughan
}
}

The params modifier

params parameter modifier may be specified on the last parameter of a method so that the method accepts any number of parameters of a particular type. The parameter type must be declared as an array



class Test {
static int Sum (params int[] ints) {
int sum = 0;
for (int i = 0; i < ints.Length; i++)
sum += ints[i]; // Increase sum by ints[i]
return sum;
}
static void Main() {
int total = Sum (1, 2, 3, 4);
Console.WriteLine (total); // 10
}
}

Optional parameters

From C# 4.0, methods, constructors, and indexers can declare optional parameters. A parameter is optional if it specifies a default value in its declaration:



void Foo (int x = 23) { Console.WriteLine (x); }



Optional parameters may be omitted when calling the method:



Foo(); // 23

Named arguments

Rather than identifying an argument by position, you can identify an argument by name.


void Foo (int x, int y) { Console.WriteLine (x + ", " + y); }
void Test() {
Foo (x:1, y:2); // 1, 2
}


Named arguments can occur in any order. The following calls to Foo are semantically identical:
Foo (x:1, y:2);
Foo (y:2, x:1);

It is often the case that you declare and initialize a variable in one step. If the compiler is able to infer the type from the initialization expression, you can use the keyword

var



var x = "hello";
var y = new System.Text.StringBuilder();
var z = (float)Math.PI;



This is precisely equivalent to:
string x = "hello";
System.Text.StringBuilder y = new System.Text.StringBuilder();
float z = (float)Math.PI;

Void Expressions


A void expression is an expression that has no value

A void expression is an expression that has no value. For example:



Console.WriteLine (1)
A void expression, since it has no value, cannot be used as an operand to build more complex expressions:
1 + Console.WriteLine (1) // Compile-time error

Shift self left by


Shift self right by


And self by


Exclusive-Or self by


Or self by

Shift self left by <<=


Shift self right by >>=


And self by &=


Exclusive-Or self by ^=


Or self by

foreach loops

foreach statement iterates over each element in an enumerable object. Most of the types in C# and the .NET Framework that represent a set or list of elements are enumerable



foreach (char c in "beer") // c is the iteration variable
Console.WriteLine (c);
OUTPUT:
b
e
e
r

namespace

A namespace is a domain for type names. Types are typically organized into hierarchical
namespaces, making them easier to find and avoiding conflicts.

namespace keyword

The namespace keyword defines a namespace for types within that block. For
example:
namespace Outer.Middle.Inner
{
class Class1 {}
class Class2 {}
}

collision. Rather than importing the whole namespace, you can import just the specific types you need, giving each type an alias. For example:

using PropertyInfo2 = System.Reflection.PropertyInfo;
class Program { PropertyInfo2 p; }

An entire namespace can be aliased, as follows

using R = System.Reflection;
class Program { R.PropertyInfo p; }

Extern

Extern aliases allow your program to reference two types with the same fully qualified
name (i.e., the namespace and type name are identical). This is an unusual
scenario and can occur only when the two types come from different assemblies

The non-nested class modifiers are

The non-nested class modifiers are


public,


internal,


abstract,


sealed,


static,


unsafe,


partial

A field is a variable that is

a member of a class or struct. For example:
class Octopus
{
string name;
public int Age = 10;
}

readonly modifier

readonly modifier prevents a field from being modified after construction. A read-only field can be assigned only in its declaration or within the enclosing type’s constructor.

Field initialization

Field initialization is optional. An uninitialized field has a default value. Field initializers run before constructors:
public int Age = 10;

Overloading constructors

A class or struct may overload constructors. To avoid code duplication, one constructor
may call another, using the this keyword:
using System;
public class Wine
{
public decimal Price;
public int Year;
public Wine (decimal price) { Price = price; }
public Wine (decimal price, int year) : this (price) { Year = year; }
}
When one constructor calls another, the called constructor executes first

Constructor and field initialization order

fields can be initialized with default values in their declaration:
class Player
{
int shields = 50; // Initialized first
int health = 100; // Initialized second
}
Field initializations occur before the constructor is executed, and in the declaration
order of the fields.

common reason to have a nonpublic constructor

A common reason to have a nonpublic constructor is to control instance creation via a static method call. The static method could be used to return an object from a pool rather than necessarily creating a new
object, or return various subclasses based on input arguments:
public class Class1
{
Class1() {} // Private constructor
public static Class1 Create (...)
{
// Perform custom logic here to return an instance of Class1
...
}
}

Properties

Properties look like fields from the outside, but internally they contain logic, like methods do. You can’t tell by looking at the following code whether CurrentPrice is a field or a property:



Stock msft = new Stock();
msft.CurrentPrice = 30;
msft.CurrentPrice -= 3;
Console.WriteLine (msft.CurrentPrice);



A property is declared like a field, but with a get/set block added



public class Stock {
decimal currentPrice; // The private "backing" field
public decimal CurrentPrice // The public property
{
get { return currentPrice; } set { currentPrice = value; }
}
}



example, the set method could throw an exception if value was outside a valid range of values.

Read-only properties

A property is read-only if it specifies only a get accessor, and it is write-only if it specifies only a set accessor. Write-only properties are rarely used

Automatic properties

automatic property declaration instructs the compiler to provide this implementation. We can redeclare the first example in this section as follows:
public class Stock
{
...
public decimal CurrentPrice { get; set; }
}

Indexers

Indexers provide a natural syntax for accessing elements in a class or struct that encapsulate a list or dictionary of values. Indexers are similar to properties, but are accessed via an index argument rather than a property name. The string class has an indexer that lets you access each of its char values via an int index:
string s = "hello";
Console.WriteLine (s[0]); // 'h'
Console.WriteLine (s[3]); // 'l'
The syntax for using indexers is like that for using arrays, except that the index argument(s) can be of any type(s).

Implementing an indexer

To write an indexer, define a property called this, specifying the arguments in square brackets. For instance:
class Sentence {
string[] words = "The quick brown fox".Split();
public string this [int wordNum] // indexer
{
get { return words [wordNum]; }
set { words [wordNum] = value; }


}
}



Here’s how we could use this indexer:
Sentence s = new Sentence();
Console.WriteLine (s[3]); // fox
s[3] = "kangaroo";
Console.WriteLine (s[3]); // kangaroo

Class fields allow for the following modifiers

Static modifier - static
Access modifiers - public, internal, private, protected
Inheritance modifier - new
Unsafe code modifier - unsafe
Read-only modifier - readonly
Threading modifier - volatile

Methods

A method performs an action in a series of statements. A method can receive input data from the caller by specifying parameters and output data back to the caller by specifying a return type. A method can specify a void return type, indicating that it doesn’t return any value to its caller. A method can also output data back to the caller via ref/out parameters.

Methods allow the following modifiers

Static modifier - static
Access modifiers - public, internal, private, protected
Inheritance modifiers - new, virtual, abstract, override, sealed
Partial method modifier - partial
Unmanaged code modifiers - unsafe, extern

Overloading methods

A type may overload methods (have multiple methods with the same name), as long as the signatures are different.


void Foo (int x) {...}
void Foo (double x) {...}
void Foo (int x, float y) {...}
void Foo (float x, int y) {...}


However, the following pairs of methods cannot coexist in the same type, since the return type and the params modifier are not part of a method’s signature:
void Foo (int x) {...}
float Foo (int x) {...} // Compile-time error
void Goo (int[] x) {...}
void Goo (params int[] x) {...} // Compile-time error

Pass-by-value versus pass-by-reference and method overloading

Whether a parameter is pass-by-value or pass-by-reference is also part of the signature. For example, Foo(int) can coexist with either Foo(ref int) or Foo(out int). However, Foo(ref int) and Foo(out int) cannot coexist:



void Foo (int x) {...}
void Foo (ref int x) {...} // OK so far
void Foo (out int x) {...} // Compile-time error

Instance Constructors

Constructors run initialization code on a class or struct. A constructor is defined like a method, except that the method name and return type are reduced to the name of
the enclosing type:
public class Panda
{
string name; // Define field
public Panda (string n) // Define constructor
{
name = n; // Initialization code (set up field)
}
}
...
Panda p = new Panda ("Petey"); // Call constructor

Instance constructors allow the following modifiers



Overloading constructors

Access modifiers - public, internal, private, protected
Unmanaged code modifiers - unsafe, extern



A class or struct may overload constructors

Implicit parameterless constructors

For classes, the C# compiler automatically generates a parameterless public constructor if and only if you do not define any constructors. However, as soon as you define at least one constructor, the parameterless constructor is no longer automatically generated.

Constructor and field initialization order

fields can be initialized with default values in their declaration:
class Player
{
int shields = 50; // Initialized first
int health = 100; // Initialized second
}
Field initializations occur before the constructor is executed, and in the declaration
order of the fields.

Nonpublic constructors

Constructors do not need to be public. A common reason to have a nonpublic constructor is to control instance creation via a static method call. The static method could be used to return an object from a pool rather than necessarily creating a new object, or return various subclasses based on input arguments:
public class Class1
{
Class1() {} // Private constructor
public static Class1 Create (...)
{
// Perform custom logic here to return an instance of Class1
...
}
}

Object Initializers Versus Optional Parameters

Instead of using object initializers, we could make Bunny’s constructor accept optional parameters:
public Bunny (string name,
bool likesCarrots = false,
bool likesHumans = false) {
Name = name;
LikesCarrots = likesCarrots;
LikesHumans = likesHumans;
}
This would allow us to construct a Bunny as follows:
Bunny b1 = new Bunny (name: "Bo", likesCarrots: true);



An advantage of this approach is that we could make Bunny’s fields (or properties, as we’ll explain shortly) read-only if we choose.



The disadvantage in this approach is that each optional parameter value is baked into the calling site. In other words, C# translates our constructor call into this:
Bunny b1 = new Bunny ("Bo", true, false);
This can be problematic if we instantiate the Bunny class from another assembly, and later modify Bunny by adding another optional parameter—such as likes Cats. Unless the referencing assembly is also recompiled.

Properties allow the following modifiers

Static modifier - static
Access modifiers - public, internal, private, protected
Inheritance modifiers - new, virtual, abstract, override, sealed
Unmanaged code modifiers - unsafe, extern

CLR indexer implementation

Indexers internally compile to methods called get_Item and set_Item, as follows:
public string get_Item (int wordNum) {...}
public void set_Item (int wordNum, string value) {...}

Static Constructors

A static constructor executes once per type, rather than once per instance. A type can define only one static constructor, and it must be parameterless and have the same name as the type:


class Test {
static Test() { Console.WriteLine ("Type Initialized"); }
}



The only modifiers allowed by static constructors are unsafe and extern.

Static Classes

A class can be marked static, indicating that it must be composed solely of static members and cannot be subclassed. The System.Console and System.Math classes are good examples of static classes.

Finalizers

Finalizers are class-only methods that execute before the garbage collector reclaims the memory for an unreferenced object. The syntax for a finalizer is the name of the class prefixed with the ~ symbol:


class Class1 {


~Class1() {
...
}
}

Partial Types and Methods

Partial types allow a type definition to be split—typically across multiple files. A common scenario is for a partial class to be auto-generated from some other source


// PaymentFormGen.cs - auto-generated
partial class PaymentForm { ... }
// PaymentForm.cs - hand-authored
partial class PaymentForm { ... }
Each participant must have the partial declaration; the following is illegal:
partial class PaymentForm {}
class PaymentForm {}
Participants cannot have conflicting members.

There are two ways to specify a base class with partial classes:

Specify the (same) base class on each participant. For example:
partial class PaymentForm : ModalForm {}
partial class PaymentForm : ModalForm {}



Specify the base class on just one participant. For example:
partial class PaymentForm : ModalForm {}
partial class PaymentForm {}

Inheritance

public class Asset {
public string Name;
}



public class Stock : Asset // inherits from Asset
{
public long SharesOwned; }
public class House : Asset // inherits from Asset
{
public decimal Mortgage;
}

Polymorphism

Polymorphism works on the basis that subclasses (Stock and House) have all the
features of their base class (Asset).

Casting and Reference Conversions

An object reference can be:
• Implicitly upcast to a base class reference
• Explicitly downcast to a subclass reference
Upcasting and downcasting between compatible reference types performs reference
conversions: a new reference is (logically) created that points to the same object. An
upcast always succeeds; a downcast succeeds only if the object is suitably typed.

The as operator

as operator performs a downcast that evaluates to null (rather than throwing an exception) if the downcast fails:
Asset a = new Asset();
Stock s = a as Stock; // s is null; no exception thrown
This is useful when you’re going to subsequently test whether the result is null:
if (s != null) Console.WriteLine (s.SharesOwned);

The is operator

is operator tests whether a reference conversion would succeed; in other words, whether an object derives from a specified class (or implements an interface). It is often used to test before downcasting.
if (a is Stock)
Console.WriteLine (((Stock)a).SharesOwned);

Virtual Function Members explanation

A function marked as virtual can be overridden by subclasses wanting to provide a specialized implementation. Methods, properties, indexers, and events can all be declared virtual

Virtual Function Members code

public class Asset {
public string Name;
public virtual decimal Liability { get { return 0; } }
}



A subclass overrides a virtual method by applying the override modifier:



public class Stock : Asset {
public long SharesOwned;
}
public class House : Asset {
public decimal Mortgage;
public override decimal Liability { get { return Mortgage; } }
}

Abstract Classes

class declared as abstract can never be instantiated. Instead, only its concrete subclasses can be instantiated.

abstract members

Abstract classes are able to define abstract members. Abstract members are like virtual
members, except they don’t provide a default implementation.



That implementation must be provided by the subclass, unless that subclass is also
declared abstract

abstract members code

public abstract class Asset {
// Note empty implementation
public abstract decimal NetValue { get; }
}
public class Stock : Asset {
public long SharesOwned;
public decimal CurrentPrice;
// Override like a virtual method.
public override decimal NetValue {
get { return CurrentPrice * SharesOwned; }
}
}

Hiding Inherited Members

A base class and a subclass may define identical members. For example:
public class A { public int Counter = 1; }
public class B : A { public int Counter = 2; }
The Counter field in class B is said to hide the Counter field in class A.



Usually, this happens by accident and generates a warning.



Occasionally, you want to hide a member deliberately, in which case you can apply
the new modifier to the member in the subclass. The new modifier does nothing more
than suppress the compiler warning that would otherwise result:
public class A { public int Counter = 1; }
public class B : A { public new int Counter = 2; }

Sealing Functions and Classes

An overridden function member may seal its implementation with the sealed keyword
to prevent it from being overridden by further subclasses



You can also seal the class itself, implicitly sealing all the virtual functions, by applying
the sealed modifier to the class itself. Sealing a class is more common than
sealing a function member.


The base Keyword

The base keyword is similar to the this keyword. It serves two essential purposes:
• Accessing an overridden function member from the subclass
• Calling a base-class constructor (see the next section)

Constructors and Inheritance

A subclass must declare its own constructors. The base class’s constructors are accessible to the derived class, but are never automatically inherited.


Any subclass must "redefine" any constructors it wants to expose., it can call any of the base class's constructors with the base keyword

Implicit calling of the parameterless base-class constructor

If a constructor in a subclass omits the base keyword, the base type’s parameterless
constructor is implicitly called:
public class BaseClass {
public int X;
public BaseClass() { X = 1; }
}
public class Subclass : BaseClass {
public Subclass() { Console.WriteLine (X); } // 1
}
If the base class has no accessible parameterless constructor, subclasses are forced to use the base keyword in their constructors.

Upcasting



Downcasting

Upcasting
An upcast operation creates a base class reference from a subclass reference



Downcasting
A downcast operation creates a subclass reference from a base class reference.

Boxing

Boxing is the act of converting a value-type instance to a reference-type instance. The reference type may be either the object class or an interface



int x = 9;
object obj = x; // Box the int

Unboxing

Unboxing reverses the operation, by casting the object back to the original value type:



int y = (int)obj; // Unbox the int



Unboxing requires an explicit cast. The runtime checks that the stated value type matches the actual object type, and throws an InvalidCastException if the check
fails.

Copying semantics of boxing and unboxing

Boxing copies the value-type instance into the new object, and unboxing copies the contents of the object back into a value-type instance. In the following example, changing the value of i doesn’t change its previously boxed copy:



int i = 3;
object boxed = i;
i = 5;
Console.WriteLine (boxed); // 3

All types in C# are represented at runtime with an instance of System.Type. There are two basic ways to get a System.Type object

• Call GetType on the instance.
• Use the typeof operator on a type name.



GetType is evaluated at runtime; typeof is evaluated statically at compile time

A struct can have all the members a class can, except the following

• A parameterless constructor
• A finalizer
• Virtual members

example of declaring and calling struct constructors

public struct Point
{
int x, y;
public Point (int x, int y) { this.x = x; this.y = y; }
}
...
Point p1 = new Point (); // p1.x and p1.y will be 0
Point p2 = new Point (1, 1); // p1.x and p1.y will be 1

Friend Assemblies

In advanced scenarios, you can expose internal members to other friend assemblies
by adding the System.Runtime.CompilerServices.InternalsVisibleTo assembly attribute,
specifying the name of the friend assembly as follows:
[assembly: InternalsVisibleTo ("Friend")]

Restrictions on Access Modifiers

Restrictions on Access Modifiers
When overriding a base class function, accessibility must be identical on the overridden
function. For example:
class BaseClass { protected virtual void Foo() {} }
class Subclass1 : BaseClass { protected override void Foo() {} } // OK
class Subclass2 : BaseClass { public override void Foo() {} } // Error

An interface is special in the following ways

• Interface members are all implicitly abstract. In contrast, a class can provide both abstract members and concrete members with implementations.
• A class (or struct) can implement multiple interfaces. In contrast, a class can inherit from only a single class, and a struct cannot inherit at all (aside from deriving from System.ValueType).

definition of the IEnumerator interface, defined in System.Collections

public interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}


// all methods are abstract a class implementing this interface will need to provide definitions


string concatenation

string s = "a" + "b";

Extending an Interface

Interfaces may derive from other interfaces. For instance:
public interface IUndoable { void Undo(); }
public interface IRedoable : IUndoable { void Redo(); }



IRedoable “inherits” all the members of IUndoable. In other words, types that implement IRedoable must also implement the members of IUndoable.


Explicit Interface Implementation def

Implementing multiple interfaces can sometimes result in a collision between member signatures. You can resolve such collisions by explicitly implementing an interface member.
Consider the following example:
interface I1 { void Foo(); }
interface I2 { int Foo(); }
public class Widget : I1, I2 {
public void Foo () {
Console.WriteLine ("Widget's implementation of I1.Foo"); }



int I2.Foo() {
Console.WriteLine ("Widget's implementation of I2.Foo");
return 42; } }

Implementing Interface Members Virtually

An implicitly implemented interface member is, by default, sealed. It must be marked virtual or abstract in the base class in order to be overridden.

Reimplementing an Interface in a Subclass

A subclass can reimplement any interface member already implemented by a base class.

In the following example, TextBox implements IUndoable.Undo explicitly, and so it cannot be marked as virtual. In order to “override” it, RichTextBox must reimplement IUndoable’s Undo method:

public interface IUndoable { void Undo(); }
public class TextBox : IUndoable
{
void IUndoable.Undo() { Console.WriteLine ("TextBox.Undo"); }
}
public class RichTextBox : TextBox, IUndoable
{
public new void Undo() { Console.WriteLine ("RichTextBox.Undo"); }
}

design a base class such that reimplementation
will never be required. There are two ways to achieve this

• When implicitly implementing a member, mark it virtual if appropriate.
• When explicitly implementing a member, use the following pattern if you anticipate that subclasses might need to override any logic:
public class TextBox : IUndoable
{
void IUndoable.Undo() { Undo(); } // Calls method below
protected virtual void Undo() { Console.WriteLine ("TextBox.Undo"); }
}
public class RichTextBox : TextBox
{
protected override void Undo() { Console.WriteLine("RichTextBox.Undo"); }
}

Interfaces and Boxing

Converting a struct to an interface causes boxing. Calling an implicitly implemented member on a struct does not cause boxing:
interface I { void Foo(); }
struct S : I { public void Foo() {} }
...
S s = new S();
s.Foo(); // No boxing.
I i = s; // Box occurs when casting to interface.
i.Foo();

Enums

public enum BorderSide { Left, Right, Top, Bottom }
We can use this enum type as follows:
BorderSide topSide = BorderSide.Top;
bool isTop = (topSide == BorderSide.Top); // true

A translation between the enum types uses the

underlying integral values:
HorizontalAlignment h = (HorizontalAlignment) BorderSide.Right;
// same as:
HorizontalAlignment h = (HorizontalAlignment) (int) BorderSide.Right;

explicitly check an enum value for validity. The static Enum.IsDefined method does this job:

BorderSide side = (BorderSide) 12345;
Console.WriteLine (Enum.IsDefined (typeof (BorderSide), side)); // False

Nested Types

A nested type is declared within the scope of another type. For example:
public class TopLevel
{
public class Nested { } // Nested class
public enum Color { Red, Blue, Tan } // Nested enum
}

A nested type has the following features

• It can access the enclosing type’s private members and everything else the enclosing type can access.
• It can be declared with the full range of access modifiers, rather than just public and internal.
• The default accessibility for a nested type is private rather than internal.
• Accessing a nested type from outside the enclosing type requires qualification with the enclosing type’s name (like when accessing static members).

Generics

C# has two separate mechanisms for writing code that is reusable across different types: inheritance and generics.



Whereas inheritance expresses reusability with a base type, generics express reusability with a “template” that contains “placeholder”
types. Generics, when compared to inheritance, can increase type safety and reduce casting and boxing.

Generic Types

A generic type declares type parameters—placeholder types to be filled in by the consumer of the generic type, which supplies the type arguments.



Stack declares a single type parameter T:
public class Stack
{
int position;
T[] data = new T[100];
public void Push (T obj) { data[position++] = obj; }
public T Pop() { return data[--position]; }
}


We can use Stack as follows:
Stack stack = new Stack();
stack.Push(5);
stack.Push(10);
int x = stack.Pop(); // x is 10
int y = stack.Pop(); // y is 5

Generic Methods

A generic method declares type parameters within the signature of a method

generic method that swaps the contents of two
variables of any type T

static void Swap (ref T a, ref T b)
{
T temp = a;
a = b;


b = temp;
}
Swap can be used as follows:
int x = 5;
int y = 10;
Swap (ref x, ref y);

Declaring Type Parameters

Type parameters can be introduced in the declaration of classes, structs, interfaces,
delegates and methods.



public struct Nullable
{
public T Value { get; }
}

The default Generic Value

The default keyword can be used to get the default value given a generic type parameter.
The default value for a reference type is null, and the default value for a value type is the result of bitwise-zeroing the value type’s fields:



static void Zap (T[] array)
{
for (int i = 0; i < array.Length; i++)
array[i] = default(T);
}

Generic Constraints

By default, a type parameter can be substituted with any type whatsoever. Constraints can be applied to a type parameter to require more specific type arguments


These are the possible constraints:
where T : base-class // Base-class constraint
where T : interface // Interface constraint
where T : class // Reference-type constraint
where T : struct // Value-type constraint (excludes Nullable types)
where T : new() // Parameterless constructor constraint
where U : T // Naked type constraint

Subclassing Generic Types

A generic class can be subclassed just like a nongeneric class. The subclass can leave the base class’s type parameters open, as in the following example:
class Stack {...}
class SpecialStack : Stack {...}

C#’s cast operator can perform several kinds of conversion, including:

• Numeric conversion
• Reference conversion
• Boxing/unboxing conversion
• Custom conversion

Covariance

Assuming A is convertible to B, X is covariant if X<A> is convertible to X<B>.



With C#’s notion of covariance (and contravariance), “convertible” means convertible via an implicit reference conversion— such as A subclassing B, or A implementing B. Numeric conversions, boxing conversions, and custom conversions are not included.

Covariance and contravariance (or simply “variance”) are advanced concepts. The motivation behind introducing and enhancing variance in C# was to

allow generic interface and generic types (in particular, those defined in the Framework, such as IEnumerable<T>) to work more as you’d expect. You can benefit from this without understanding the details behind covariance
and contravariance.

array types are covariant

For historical reasons, array types are covariant. This means that B[] can be cast to
A[] if B subclasses A (and both are reference types). For example:
Bear[] bears = new Bear[3];
Animal[] animals = bears; // OK
The downside of this reusability is that element assignments can fail at runtime:
animals[0] = new Camel(); // Runtime error

Contravariance

We previously saw that, assuming that A allows an implicit reference conversion to B, a type X is covariant if X<A> allows a reference conversion to X<B>. A type is contravariant when you can convert in the reverse direction—from X<B> to X<A>.

consider the Max method in C#, once more:
static T Max <T> (T a, T b) where T : IComparable<T> {
return a.CompareTo (b) > 0 ? a : b;
}
Why couldn’t we have implemented it like this?
static T Max <T> (T a, T b) {
return a > b ? a : b; // Compile error
}

The reason is that Max needs to be compiled once and work for all possible values of T. Compilation cannot succeed, because there is no single meaning for > across all values of T—in fact, not every T even has a > operator. In contrast, the following code shows the same Max method written with C++ templates. This code will be compiled separately for each value of T,

Delegates def

A delegate is an object that knows how to call a method.
A delegate type defines the kind of method that delegate instances can call. Specifically, it defines the method’s return type and its parameter types.

The following defines a delegate type called Transformer:

delegate int Transformer (int x);


Transformer is compatible with any method with an int return type and a single int parameter, such as this:
static int Square (int x) { return x * x; }


Assigning a method to a delegate variable creates a delegate instance:
Transformer t = Square;
which can be invoked in the same way as a method:
int answer = t(3); // answer is 9