Medium 9780596519223

C# 3.0 Pocket Reference: Instant Help for C# 3.0 Programmers

Views: 2244
Ratings: (0)

This book is for busy programmers who want a succinct and yet readable guide to C# 3.0 and LINQ. C# 3.0 Pocket Reference tells you exactly what you need to know, without long introductions or bloated samples.

Despite its conciseness, this book doesn't skimp on depth or detail, and embraces the conceptual challenges in learning C# 3.0 and LINQ. Tightly focused and highly practical, this pocket reference covers more ground than many of the big books on C#.

C# 3.0 Pocket Reference includes plenty of illustrations and code examples to explain:

  • Features new to C# 3.0, such as lambda expressions, anonymous types, automatic properties, and more
  • All aspects of C# syntax, predefined types, expressions, and operators
  • Creating classes, structs, delegates and events, enums, generics and constraints, exception handling, and iterators
  • The subtleties of boxing, operating overloading, delegate covariance, extension method resolution, interface reimplementation, nullable types, and operating lifting
  • LINQ, starting with the principles of sequences, deferred execution and standard query operators, and finishing with a complete reference to query syntax-including multiple generators, joining, grouping, and query continuations
  • Consuming, writing, and reflecting on custom attributes

You'll also find chapters on unsafe code and pointers, preprocessor directives, XML documentation, and a framework overview. If you're already familiar with Java, C++, or an earlier version of C#, C# 3.0 Pocket Reference is an ideal choice.

No other book or online resource can get you up to speed so quickly.

List price: $11.99

Your Price: $9.59

You Save: 20%


37 Slices

Format Buy Remix

What's New in C# 3.0


C# is a general-purpose, type-safe, object-oriented programming language whose goal is programmer productivity. To this end, the language balances simplicity, expressiveness, and performance. The C# language is platform-neutral, but it was written to work well with the Microsoft .NET Framework. C# 3.0 targets .NET Framework 3.5.

C# 3.0 features are centered on Language Integrated Query capabilities, or LINQ for short. LINQ enables SQL-like queries to be written directly within a C# program, and checked statically for correctness. Queries can execute either locally or remotely; the .NET Framework provides LINQ-enabled APIs across local collections, remote databases, and XML.

C# 3.0 features include:

Lambda expressions

Extension methods

Implicitly typed local variables

Query comprehensions

Anonymous types

Implicitly typed arrays

Object initializers

Automatic properties

Partial methods

Expression trees

Lambda expressions are like miniature functions created on the fly. They are a natural evolution of anonymous methods introduced in C# 2.0, and in fact, completely subsume the functionality of anonymous methods. For example:


A First C# Program


Here is a program that multiplies 12 x 30, and prints the result, 360, to the screen. The double-forward slash indicates that the remainder of a line is a comment.

At the heart of this program lie two statements. Statements in C# execute sequentially. Each statement is terminated by a semicolon:

The first statement computes the expression 12 * 30 and stores the result in a local variable, named x, which is an integer type. The second statement calls the Console class's WriteLine method to print the variable x to a text window on the screen.

A method performs an action in a series of statements, called a statement blocka pair of braces containing zero or more statements. We defined a single method named Main:

Writing higher-level functions that call upon lower-level functions simplifies a program. We can refactor our program with a reusable method that multiplies an integer by 12 as follows:

A method can receive input data from the caller by specifying parameters, and output data back to the caller by specifying a return type. We defined a method called FeetToInches that has a parameter for inputting feet, and a return type for outputting inches:




C# syntax is based on C and C++ syntax. In this section, we describe C#'s elements of syntax, using the following program:

Identifiers are names that programmers choose for their classes, methods, variables, and so on. These are the identifiers in our example program in the order in which they appear:

An identifier must be a whole word, essentially made up of Unicode characters starting with a letter or underscore. C# identifiers are case-sensitive. By convention, arguments, local variables, and private fields should be in camel case (e.g., myVariable), and all other identifiers should be in Pascal case (e.g., MyMethod).

Keywords are names reserved by the compiler that you can't use as identifiers. These are the keywords in our example program:

Here is the full list of C# keywords:




























Type Basics


A type defines the blueprint for a value. A value is a storage location denoted by a variable or a constant. A variable represents a value that can change, whereas a constant represents an invariant. We created a local variable named x in our first program:

All values in C# are instances of a specific type. The meaning of a value, and the set of possible values a variable can have, is determined by its type. The type of x is int.

Predefined types are types that are specially supported by the compiler. The int type is a predefined primitive type for representing the set of integers that fits into 32 bits of memory, from 231 to 2311. We can perform functions such as arithmetic with instances of the int type, as follows:

Another predefined C# type is the string type. The string type represents a sequence of characters, such as ".NET" or We can manipulate strings by calling functions on them as follows:


Numeric Types


C# has the following predefined numeric types.

C# type

System type







8 bits

27 to 271



16 bits

215 to 2151



32 bits

231 to 2311




64 bits

263 to 2631




8 bits

0 to 281



16 bits

0 to 2161




32 bits

0 to 2321




64 bits

0 to 2641





32 bits

( ~1045 to 1038)




64 bits

( ~10324 to 10308)




128 bits

( ~1028 to 1028)

Of the integral types, int and long are first-class citizens and C# and the runtime favor both. The other integral types are typically used for interoperability or when space efficiency is paramount.

Of the real number types, float and double are called floating-point types and are typically used for scientific calculations. The decimal type is typically used for financial calculations, where base-10-accurate arithmetic and high precision are required.[1]


Boolean Type and Operators


C#'s bool type (aliasing the System.Boolean type) is a logical value that can be assigned the literal true or false.

Although a Boolean value requires only one bit (zero or one) of storage, the runtime will use one or two bytes of memory, as this is the minimum chunk that the runtime and processor can efficiently work with. To avoid space-inefficiency in the case of arrays, the Framework provides a BitArray class in the System.Collections namespace, which is designed to use just one bit per Boolean value.

= = and != test for equality and inequality of any type, but always return a bool value. Value types typically have a very simple notion of equality:

For reference types, equality, by default, is based on reference, as opposed to the actual value of the underlying object:

The comparison operators, <, >, <=, and >=, work for all numeric types, but should be used with caution with real numbers (see the previous section "Real Number Rounding Errors"). The comparison operators also work on enum type members, by comparing their underlying integral values.


Strings and Characters


C#'s char type (aliasing the System.Char type) represents a Unicode character, and it occupies two bytes. A char literal is specified inside single quotes:

Escape sequencesexpress characters that cannot be expressed or interpreted literally. An escape sequence is a backslash followed by a character with a special meaning. For example:

The escape sequence characters are outlined below.





Single quote



Double quote















Form feed



New line



Carriage return



Horizontal tab



Vertical tab


The \u (or \x) escape sequence lets you specify any Unicode character via its four-digit hexadecimal code:

An implicit conversion from a char to a numeric type works for the numeric types that can accommodate an unsigned short. For other numeric types, an explicit conversion is required.

C#'s string type (aliasing the System.String type) represents an immutable sequence of Unicode characters. A string literal is specified inside double quotes:




An array represents a fixed number of elements of a particular type. The elements in an array are always stored in a contiguous block of memory, providing highly efficient access.

An array is denoted with square brackets after the element type. For example:

Square brackets also index the array, accessing a particular element by position:

This prints "e" because array indexes start at zero. We can use a for loop statement to iterate through each element in the array. The for loop in this example cycles the integer i from 0 to 4:

Arrays also implement IEnumerable<T>, so you can enumerate members with the foreach statement:

The Length property of an array returns the number of elements in the array. Once an array has been created, its length cannot be changed. The System.Collection namespace and subnamespaces provide higher-level data structures, such as dynamically sized arrays and dictionaries.

An array initialization expression specifies each element of an array. For example:


Variables and Parameters


A variable represents a storage location that has a modifiable value. A variable can be a local variable, parameter (value, ref, or out), field (instance or static), or array element.

The stack and the heap are the places where variables and constants reside. Each has very different lifetime semantics.

The stack is a block of memory for storing local variables and parameters. The stack automatically grows and shrinks as a function is entered and exited. Consider the following method (to avoid distraction, input argument checking is ignored):

This method is recursive, meaning that it calls itself. Each time the method is entered, a new int is allocated on the stack, and each time the method exits, the int is deallocated.

The heap is a block of memory in which objects (i.e., reference type instances) reside. Whenever a new object is created, it is allocated on the heap, and a reference to that object is returned. During a program's execution, the heap starts filling up as new objects are created. The runtime has a garbage collector that periodically deallocates objects from the heap, so your computer does not run out of memory. An object is eligible for deallocation as soon as nothing references it. In the following example, the StringBuilder object is created on the heap, while the sb reference is created on the stack:


Expressions and Operators


An expression essentially denotes a value. The simplest kinds of expressions are constants and variables. Expressions can be transformed and combined using operators. An operator takes one or more input operands to output a new expression.

Here is an example of a constant expression:

We can use the * operator to combine two operands (the literal expressions 12 and 30), as follows:

Complex expressions can be built because an operand may itself be an expression, such as the operand (12*30) in the following example:

Operators in C# are classed as unary, binary, or ternary depending on the number of operands they work on (one, two, or three). The binary operators always use infix notation, where the operator is placed between the two operands.

Primary expressions include expressions composed of operators that are intrinsic to the basic plumbing of the language. Here is an example:

This expression is composed of two primary expressions. The first expression performs a member-lookup (with the . operator), and the second expression performs a method call (with the () operator).




Functions comprise statements that execute sequentially in the textual order in which they appear. A statement block is a series of statements appearing between braces (the {} tokens).

A declaration statement declares a new variable, optionally initializing the variable with an expression. A declaration statement ends in a semicolon. You may declare multiple variables of the same type in a comma-separated list. For example:

A constant declaration is like a variable declaration, except that the variable cannot be changed after it has been declared, and the initialization must occur with the declaration:

The scope of a local or constant variable extends to the end of the current block. You cannot declare another local variable with the same name in the current block or in any nested blocks. For example:

Expression statements are expressions that are also valid statements. An expression statement must either change state or call something that might change state. Changing state essentially means changing a variable. The possible expression statements are:




A namespace is a domain within which type names must be unique. Types are typically organized into hierarchical namespacesboth to avoid naming conflicts and to make type names easier to find. For example, the RSA type, which handles public key encryption, is defined within the following namespace:

A namespace forms an integral part of a type's name. The following code calls RSA's Create method:

Namespaces are independent of assemblies, which are units of deployment such as an .exe or .dll. Namespaces also have no impact on member visibilitypublic, internal, private, and so on.

The namespace keyword defines a type within a namespace. For example:

The dots in the namespace indicate a hierarchy of nested namespaces. The following is semantically identical to the preceding example:

You can refer to a type with is fully qualified name, which includes all namespaces from the outermost to the innermost. For example, we could refer to Class1 in the preceding example as Outer.Middle.Inner.Class1.




A class is the most common kind of reference type. The simplest possible class declaration is as follows:

A more complex class optionally has:

preceding the keyword class

attributes and class modifiers. The non-nested class modifiers are public, internal, abstract, sealed, static, unsafe, and partial

following YourClassName

generic type parameters, a base class, and interfaces

within the braces

class members (these are methods, properties, indexers, events, fields, constructors, operator functions, nested types, and a finalizer)

A field is a variable that is a member of a class or struct. For example:

A field may have the readonly modifier to prevent it 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 is optional. An uninitialized field has a default value (0, \0, null, false). Field initializers run before constructors:




A class can inherit from another class to extend or customize the original class. Inheriting from a class lets you reuse the functionality in that class instead of building it from scratch. A class can inherit from only a single class, but can itself be inherited by many classes, thus forming a class hierarchy. In this example, we start by defining a class called Asset:

Next, we define classes called Stock and House, which will inherit from Asset. Stock and House get everything an Asset has, plus any additional members that they define:

Here's how we can use these classes:

The subclasses Stock and House inherit the Name property from the base class Asset.

A subclass is also called a derived class. A base class is also called a superclass.

References are polymorphic, which means a reference to a base class can refer to an instance of a subclass. For instance, consider the following method:


The object Type


object (System.Object) is the ultimate base class for all types. Any type can be upcast to object.

To illustrate how this is useful, consider a general-purpose stack. A stack is a data structure based on the principle of LIFO"Last in, First out." A stack has two operations: push an object on the stack, and pop an object off the stack.

Here is a simple implementation that can hold up to 10 objects:

Because Stack works with the object type, we can Push and Pop instances of any type to and from the Stack:

object is a reference type, by virtue of being a class. Despite this, value types, such as int, can also be cast to and from object, and so be added to our stack. This feature of C# is called type unification:

When you cast between a value type and object, the CLR must perform some special work to bridge the difference in semantics between value and reference types. This process is called boxing and unboxing.




A struct is similar to a class, with the following key differences:

A struct is a value type, whereas a class is a reference type.

A struct does not support inheritance (other than implicitly deriving from object).

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

A parameterless constructor

A finalizer

Virtual members

A struct is used instead of a class when value type semantics are desirable. Good examples of structs are numeric types, where it is more natural for assignment to copy a value rather than a reference. Because a struct is a value type, each instance does not require instantiation of an object on the heap. This can be important when creating many instances of a type, for example, with an array.

The construction semantics of a struct are as follows:

A parameterless constructor implicitly exists, which you can't override. This performs a bitwise-zeroing of its fields.

When you define a struct constructor, you must explicitly assign every field.


Access Modifiers


To promote encapsulation, a type or type member may limit its accessibility to other types and other assemblies by adding one of five access modifiers to the declaration:

Fully accessible. The implicit accessibility for members of an enum or interface.

Accessible only within containing assembly or friend assemblies. The default accessibility for nonnested types.

Visible only within containing type. The default accessibility members of a class or struct.

Visible only within containing type or subclasses.

The union of protected and internal accessibility. (This is less restrictive than protected or internal alone.)

The CLR has the concept of the intersection of protected and internal accessibility, but C# does not support this.

Class2 is accessible from outside its assembly; Class1 is not:

ClassB exposes field x to other types in the same assembly; ClassA does not:

Functions within Subclass can call Bar but not Foo:




An interface is similar to a class, but it provides a specification rather than an implementation for its members. An interface is special in the following ways:

A class can implement multiple interfaces. In contrast, a class can inherit from only a single class.

Interface members are all implicitly abstract. In contrast, a class can provide both abstract members and concrete members with implementations.

Structs can implement interfaces. In contrast, a struct cannot inherit from a class.

An interface declaration is like a class declaration, but it provides no implementation for its members, as all its members are implicitly abstract. These members will be implemented by the classes and structs that implement the interface. An interface can contain only methods, properties, events, and indexers, which noncoincidentally are precisely the members of a class that can be abstract.

Here is a slightly simplified version of the IEnumerator interface, defined in System.Collections:


Load more


Print Book

Format name
File size
0 Bytes
Not Allowed
Not Allowed
Read aloud
Format name
Read aloud
In metadata
In metadata
File size
In metadata