Contents

Special Thanks

Preface

Part I The C# Language

1 The Creation of C#

C#’s Family Tree

C: The Beginning of the Modern Age of Programming

The Creation of OOP and C++

The Internet and Java Emerge

The Creation of C#

The Evolution of C#

How C# Relates to the .NET Framework

What Is the .NET Framework?

How the Common Language Runtime Works

Managed vs. Unmanaged Code

The Common Language Specification

2 An Overview of C#

Object-Oriented Programming

Encapsulation

Polymorphism

Inheritance

A First Simple Program

Using csc.exe, the C# Command-Line Compiler

Using the Visual Studio IDE

The First Sample Program, Line by Line

Handling Syntax Errors

A Small Variation

A Second Simple Program

Another Data Type

Two Control Statements

The if Statement

The for Loop

Using Code Blocks

Semicolons, Positioning, and Indentation

The C# Keywords

Identifiers

The .NET Framework Class Library

3 Data Types, Literals, and Variables

Why Data Types Are Important

C#’s Value Types

Integers

Floating-Point Types

The decimal Type

Characters

The bool Type

Some Output Options

Literals

Hexadecimal Literals

Character Escape Sequences

String Literals

A Closer Look at Variables

Initializing a Variable

Dynamic Initialization

Implicitly Typed Variables

The Scope and Lifetime of Variables

Type Conversion and Casting

Automatic Conversions

Casting Incompatible Types

Type Conversion in Expressions

Using Casts in Expressions

4 Operators

Arithmetic Operators

Increment and Decrement

Relational and Logical Operators

Short-Circuit Logical Operators

The Assignment Operator

Compound Assignments

The Bitwise Operators

The Bitwise AND, OR, XOR, and NOT Operators

The Shift Operators

Bitwise Compound Assignments

The ? Operator

Spacing and Parentheses

Operator Precedence

5 Program Control Statements

The if Statement

Nested ifs

The if-else-if Ladder

The switch Statement

Nested switch Statements

The for Loop

Some Variations on the for Loop

The while Loop

The do-while Loop

The foreach Loop

Using break to Exit a Loop

Using continue

return

The goto

6 Introducing Classes and Objects

Class Fundamentals

The General Form of a Class

Define a Class

How Objects Are Created

Reference Variables and Assignment

Methods

Add a Method to the Building Class

Return from a Method

Return a Value

Use Parameters

Add a Parameterized Method to Building

Avoiding Unreachable Code

Constructors

Parameterized Constructors

Add a Constructor to the Building Class

The new Operator Revisited

Using new with Value Types

Garbage Collection and Destructors

Destructors

The this Keyword

7 Arrays and Strings

Arrays

One-Dimensional Arrays

Multidimensional Arrays

Two-Dimensional Arrays

Arrays of Three or More Dimensions

Initializing Multidimensional Arrays

Jagged Arrays

Assigning Array References

Using the Length Property

Using Length with Jagged Arrays

Implicitly Typed Arrays

The foreach Loop

Strings

Constructing Strings

Operating on Strings

Arrays of Strings

Strings Are Immutable

Strings Can Be Used in switch Statements

8 A Closer Look at Methods and Classes

Controlling Access to Class Members

C#’s Access Modifiers

Applying Public and Private Access

Controlling Access: A Case Study

Pass References to Methods

How Arguments Are Passed

Use ref and out Parameters

Use ref

Use out

Use ref and out on References

Use a Variable Number of Arguments

Return Objects

Return an Array

Method Overloading

Overload Constructors

Invoke an Overloaded Constructor Through this

Object Initializers

Optional Arguments

Optional Arguments vs. Overloading

Optional Arguments and Ambiguity

A Practical Example of Optional Arguments

Named Arguments

The Main( ) Method

Return Values from Main( )

Pass Arguments to Main( )

Recursion

Understanding static

Static Constructors

Static Classes

9 Operator Overloading

Operator Overloading Fundamentals

Overloading Binary Operators

Overloading Unary Operators

Handling Operations on C# Built-in Types

Overloading the Relational Operators

Overloading true and false

Overloading the Logical Operators

A Simple Approach to Overloading the Logical Operators

Enabling the Short-Circuit Operators

Conversion Operators

Operator Overloading Tips and Restrictions

Another Example of Operator Overloading

10 Indexers and Properties

Indexers

Creating One-Dimensional Indexers

Indexers Can Be Overloaded

Indexers Do Not Require an Underlying Array

Multidimensional Indexers

Properties

Auto-Implemented Properties

Use Object Initializers with Properties

Property Restrictions

Use Access Modifiers with Accessors

Using Indexers and Properties

11 Inheritance

Inheritance Basics

Member Access and Inheritance

Using Protected Access

Constructors and Inheritance

Calling Base Class Constructors

Inheritance and Name Hiding

Using base to Access a Hidden Name

Creating a Multilevel Hierarchy

When Are Constructors Called?

Base Class References and Derived Objects

Virtual Methods and Overriding

Why Overridden Methods?

Applying Virtual Methods

Using Abstract Classes

Using sealed to Prevent Inheritance

The object Class

Boxing and Unboxing

Is object a Universal Data Type?

12 Interfaces, Structures, and Enumerations

Interfaces

Implementing Interfaces

Using Interface References

Interface Properties

Interface Indexers

Interfaces Can Be Inherited

Name Hiding with Interface Inheritance

Explicit Implementations

Choosing Between an Interface and an Abstract Class

The .NET Standard Interfaces

Structures

Why Structures?

Enumerations

Initialize an Enumeration

Specify the Underlying Type of an Enumeration

Use Enumerations

13 Exception Handling

The System.Exception Class

Exception-Handling Fundamentals

Using try and catch

A Simple Exception Example

A Second Exception Example

The Consequences of an Uncaught Exception

Exceptions Let You Handle Errors Gracefully

Using Multiple catch Clauses

Catching All Exceptions

Nesting try Blocks

Throwing an Exception

Rethrowing an Exception

Using finally

A Closer Look at the Exception Class

Commonly Used Exceptions

Deriving Exception Classes

Catching Derived Class Exceptions

Using checked and unchecked

14 Using I/O

C#’s I/O Is Built Upon Streams

Byte Streams and Character Streams

The Predefined Streams

The Stream Classes

The Stream Class

The Byte Stream Classes

The Character Stream Wrapper Classes

Binary Streams

Console I/O

Reading Console Input

Using ReadKey( )

Writing Console Output

FileStream and Byte-Oriented File I/O

Opening and Closing a File

Reading Bytes from a FileStream

Writing to a File

Using FileStream to Copy a File

Character-Based File I/O

Using StreamWriter

Using a StreamReader

Redirecting the Standard Streams

Reading and Writing Binary Data

BinaryWriter

BinaryReader

Demonstrating Binary I/O

Random Access Files

Using MemoryStream

Using StringReader and StringWriter

The File Class

Using Copy( ) to Copy a File

Using Exists( ) and GetLastAccessTime( )

Converting Numeric Strings to Their Internal Representation

15 Delegates, Events, and Lambda Expressions

Delegates

Delegate Method Group Conversion

Using Instance Methods as Delegates

Multicasting

Covariance and Contravariance

System.Delegate

Why Delegates

Anonymous Functions

Anonymous Methods

Pass Arguments to an Anonymous Method

Return a Value from an Anonymous Method

Use Outer Variables with Anonymous Methods

Lambda Expressions

The Lambda Operator

Expression Lambdas

Statement Lambdas

Events

A Multicast Event Example

Instance Methods vs. Static Methods as Event Handlers

Using Event Accessors

Miscellaneous Event Features

Use Anonymous Methods and Lambda Expressions with Events

.NET Event Guidelines

Use EventHandler<TEventArgs> and EventHandler

Applying Events: A Case Study

16 Namespaces, the Preprocessor, and Assemblies

Namespaces

Declaring a Namespace

Namespaces Prevent Name Conflicts

using

A Second Form of using

Namespaces Are Additive

Namespaces Can Be Nested

The Global Namespace

Using the:: Namespace Alias Qualifier

The Preprocessor

#define

#if and #endif

#else and #elif

#undef

#error

#warning

#line

#region and #endregion

#pragma

Assemblies and the internal Access Modifier

The internal Access Modifier

17 Runtime Type ID, Reflection, and Attributes

Runtime Type Identification

Testing a Type with is

Using as

Using typeof

Reflection

The Reflection Core: System.Type

Using Reflection

Obtaining Information About Methods

Calling Methods Using Reflection

Obtaining a Type’s Constructors

Obtaining Types from Assemblies

Fully Automating Type Discovery

Attributes

Attribute Basics

Positional vs. Named Parameters

Three Built-in Attributes

AttributeUsage

The Conditional Attribute

The Obsolete Attribute

18 Generics

What Are Generics?

A Simple Generics Example

Generic Types Differ Based on Their Type Arguments

How Generics Improve Type Safety

A Generic Class with Two Type Parameters

The General Form of a Generic Class

Constrained Types

Using a Base Class Constraint

Using an Interface Constraint

Using the new( ) Constructor Constraint

The Reference Type and Value Type Constraints

Using a Constraint to Establish a Relationship Between Two Type Parameters

Using Multiple Constraints

Creating a Default Value of a Type Parameter

Generic Structures

Creating a Generic Method

Using Explicit Type Arguments to Call a Generic Method

Using a Constraint with a Generic Method

Generic Delegates

Generic Interfaces

Comparing Instances of a Type Parameter

Generic Class Hierarchies

Using a Generic Base Class

A Generic Derived Class

Overriding Virtual Methods in a Generic Class

Overloading Methods That Use Type Parameters

Covariance and Contravariance in Generic Type Parameters

Using Covariance in a Generic Interface

Using Contravariance in a Generic Interface

Variant Delegates

How Generic Types Are Instantiated

Some Generic Restrictions

Final Thoughts on Generics

19 LINQ

LINQ Fundamentals

A Simple Query

A Query Can Be Executed More Than Once

How the Data Types in a Query Relate

The General Form of a Query

Filter Values with where

Sort Results with orderby

A Closer Look at select

Use Nested from Clauses

Group Results with group

Use into to Create a Continuation

Use let to Create a Variable in a Query

Join Two Sequences with join

Anonymous Types

Create a Group Join

The Query Methods

The Basic Query Methods

Create Queries by Using the Query Methods

Query Syntax vs. Query Methods

More Query-Related Extension Methods

Deferred vs. Immediate Query Execution

Expression Trees

Extension Methods

PLINQ

20 Unsafe Code, Pointers, Nullable Types, Dynamic Types, and Miscellaneous Topics

Unsafe Code

Pointer Basics

Using unsafe

Using fixed

Accessing Structure Members Through a Pointer

Pointer Arithmetic

Pointer Comparisons

Pointers and Arrays

Pointers and Strings

Multiple Indirection

Arrays of Pointers

stackalloc

Creating Fixed-Size Buffers

Nullable Types

Nullable Basics

Nullable Objects in Expressions

The ?? Operator

Nullable Objects and the Relational and Logical Operators

Partial Types

Partial Methods

Create a Dynamic Type with dynamic

COM Interoperability

Friend Assemblies

Miscellaneous Keywords

lock

readonly

const and volatile

The using Statement

extern

Part II Exploring the C# Library

21 Exploring the System Namespace

The Members of System

The Math Class

The .NET Structures Corresponding to the Built-in Value Types

The Integer Structures

The Floating-Point Structures

Decimal

Char

The Boolean Structure

The Array Class

Sorting and Searching Arrays

Reversing an Array

Copying an Array

Using a Predicate

Using an Action

BitConverter

Generating Random Numbers with Random

Memory Management and the GC Class

Object

Tuple

The IComparable and IComparable<T> Interfaces

The IEquatable<T> Interface

The IConvertible Interface

The ICloneable Interface

IFormatProvider and IFormattable

IObservable<T> and IObserver<T>

22 Strings and Formatting

Strings in C#

The String Class

The String Constructors

The String Field, Indexer, and Property

The String Operators

The String Methods

Padding and Trimming Strings

Inserting, Removing, and Replacing

Changing Case

Using the Substring( ) Method

The String Extension Methods

Formatting

Formatting Overview

The Numeric Format Specifiers

Understanding Argument Numbers

Using String.Format( ) and ToString( ) to Format Data

Using String.Format( ) to Format Values

Using ToString( ) to Format Data

Creating a Custom Numeric Format

The Custom Format Placeholder Characters

Formatting Date and Time

Creating a Custom Date and Time Format

Formatting Time Spans

Formatting Enumerations

23 Multithreaded Programming, Part One

Multithreading Fundamentals

The Thread Class

Creating and Starting a Thread

Some Simple Improvements

Creating Multiple Threads

Determining When a Thread Ends

Passing an Argument to a Thread

The IsBackground Property

Thread Priorities

Synchronization

An Alternative Approach

The Monitor Class and lock

Thread Communication Using Wait( ), Pulse( ), and PulseAll( )

An Example That Uses Wait( ) and Pulse( )

Deadlock and Race Conditions

Using MethodImplAttribute

Using a Mutex and a Semaphore

The Mutex

The Semaphore

Using Events

The Interlocked Class

Synchronization Classes Added by .NET 4.0

Terminating a Thread Via Abort( )

An Abort( ) Alternative

Canceling Abort( )

Suspending and Resuming a Thread

Determining a Thread’s State

Using the Main Thread

Additional Multithreading Features Added by .NET 4.0

Multithreading Tips

Starting a Separate Task

24 Multithreading, Part Two: Exploring the Task Parallel Library and PLINQ

Two Approaches to Parallel Programming

The Task Class

Creating a Task

Use a Task ID

Using Wait Methods

Calling Dispose( )

Using TaskFactory to Start a Task

Use a Lambda Expression as a Task

Create a Task Continuation

Returning a Value from a Task

Cancelling a Task and Using AggregateException

Some Other Task Features

The Parallel Class

Parallelizing Tasks via Invoke( )

Using the For( ) Method

Using the ForEach( ) Method

Exploring PLINQ

ParallelEnumerable

Parallelizing a Query with AsParallel( )

Using AsOrdered( )

Cancelling a Parallel Query

Other PLINQ Features

PLINQ Efficiency Concerns

25 Collections, Enumerators, and Iterators

Collections Overview

The Non-Generic Collections

The Non-Generic Interfaces

The DictionaryEntry Structure

The Non-Generic Collection Classes

Storing Bits with BitArray

The Specialized Collections

The Generic Collections

The Generic Interfaces

The KeyValuePair<TKey, TValue> Structure

The Generic Collection Classes

The Concurrent Collections

Storing User-Defined Classes in Collections

Implementing IComparable

Implementing IComparable for Non-Generic Collections

Implementing IComparable<T> for Generic Collections

Using an IComparer

Using a Non-Generic IComparer

Using a Generic IComparer<T>

Using StringComparer

Accessing a Collection via an Enumerator

Using an Enumerator

Using IDictionaryEnumerator

Implementing IEnumerable and IEnumerator

Using Iterators

Stopping an Iterator

Using Multiple yield Directives

Creating a Named Iterator

Creating a Generic Iterator

Collection Initializers

26 Networking Through the Internet Using System.Net

The System.Net Members

Uniform Resource Identifiers

Internet Access Fundamentals

WebRequest

WebResponse

HttpWebRequest and HttpWebResponse

A Simple First Example

Handling Network Errors

Exceptions Generated by Create( )

Exceptions Generated by GetReponse( )

Exceptions Generated by GetResponseStream( )

Using Exception Handling

The URI Class

Accessing Additional HTTP Response Information

Accessing the Header

Accessing Cookies

Using the LastModified Property

MiniCrawler: A Case Study

Using WebClient

A Documentation Comment Quick Reference

The XML Comment Tags

Compiling Documentation Comments

An XML Documentation Example

Index