CARVIEW |
Select Language
HTTP/2 302
server: nginx
date: Sat, 02 Aug 2025 21:36:09 GMT
content-type: text/plain; charset=utf-8
content-length: 0
x-archive-redirect-reason: found capture at 20080520072609
location: https://web.archive.org/web/20080520072609/https://www.oreilly.com/catalog/9780596004293/toc.html
server-timing: captures_list;dur=28.469060, exclusion.robots;dur=0.027908, exclusion.robots.policy;dur=0.013059, esindex;dur=0.020057, cdx.remote;dur=32.652475, LoadShardBlock;dur=176.452516, PetaboxLoader3.datanode;dur=63.722437, PetaboxLoader3.resolve;dur=85.448097
x-app-server: wwwb-app223
x-ts: 302
x-tr: 265
server-timing: TR;dur=0,Tw;dur=0,Tc;dur=0
set-cookie: wb-p-SERVER=wwwb-app223; path=/
x-location: All
x-rl: 0
x-na: 0
x-page-cache: MISS
server-timing: MISS
x-nid: DigitalOcean
referrer-policy: no-referrer-when-downgrade
permissions-policy: interest-cohort=()
HTTP/2 200
server: nginx
date: Sat, 02 Aug 2025 21:36:10 GMT
content-type: text/html
x-archive-orig-date: Tue, 20 May 2008 07:25:46 GMT
x-archive-orig-server: Apache
x-archive-orig-p3p: policyref="https://www.oreillynet.com/w3c/p3p.xml",CP="CAO DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONo OUR DELa PUBi OTRa IND PHY ONL UNI PUR COM NAV INT DEM CNT STA PRE"
x-archive-orig-last-modified: Sat, 17 May 2008 01:28:08 GMT
x-archive-orig-accept-ranges: bytes
x-archive-orig-content-length: 148308
x-archive-orig-x-cache: MISS from olive.bp
x-archive-orig-x-cache-lookup: MISS from olive.bp:3128
x-archive-orig-via: 1.0 olive.bp:3128 (squid/2.6.STABLE13)
x-archive-orig-connection: close
x-archive-guessed-content-type: text/html
x-archive-guessed-charset: utf-8
memento-datetime: Tue, 20 May 2008 07:26:09 GMT
link: ; rel="original", ; rel="timemap"; type="application/link-format", ; rel="timegate", ; rel="first memento"; datetime="Tue, 20 May 2008 07:26:09 GMT", ; rel="memento"; datetime="Tue, 20 May 2008 07:26:09 GMT", ; rel="next memento"; datetime="Sat, 14 Jun 2008 02:32:48 GMT", ; rel="last memento"; datetime="Fri, 03 Jul 2009 01:49:39 GMT"
content-security-policy: default-src 'self' 'unsafe-eval' 'unsafe-inline' data: blob: archive.org web.archive.org web-static.archive.org wayback-api.archive.org athena.archive.org analytics.archive.org pragma.archivelab.org wwwb-events.archive.org
x-archive-src: 52_3_20080520055547_crawl101-c/52_3_20080520072545_crawl100.arc.gz
server-timing: captures_list;dur=2.299195, exclusion.robots;dur=0.031680, exclusion.robots.policy;dur=0.015007, esindex;dur=0.017893, cdx.remote;dur=21.836342, LoadShardBlock;dur=301.461214, PetaboxLoader3.datanode;dur=122.199941, PetaboxLoader3.resolve;dur=520.169115, load_resource;dur=373.347277
x-app-server: wwwb-app223
x-ts: 200
x-tr: 821
server-timing: TR;dur=0,Tw;dur=0,Tc;dur=0
x-location: All
x-rl: 0
x-na: 0
x-page-cache: MISS
server-timing: MISS
x-nid: DigitalOcean
referrer-policy: no-referrer-when-downgrade
permissions-policy: interest-cohort=()
content-encoding: gzip
O'Reilly Media | C# Language Pocket Reference
Buy this Book
C# Language Pocket Reference
By Peter Drayton, Ben Albahari, Ted Neward
Cover | Table of Contents
Table of Contents
- Chapter : C# Language Pocket Reference
- Content preview·Buy reprint rights for this chapterC# is a programming language from Microsoft that is designed specifically to target the .NET Framework. Microsoft's .NET Framework is a runtime environment and class library that dramatically simplifies the development of modern, component-based applications.Microsoft has shown an unprecedented degree of openness in C# and the .NET Framework. The key specifications for the C# language and the .NET platform have been published, reviewed, and ratified by an international standards organization called the European Computer Manufacturers Association (ECMA). This standardization effort has led to a Shared Source release of the specification called the Shared Source CLI (
https://msdn.microsoft.com/net/sscli/
), as well as to Open Source implementations of .NET called DotGNU Portable .NET (https://www.dotgnu.org
) and Mono (https://www.go-mono.com
). All three implementations include support for C#.This book is a quick-reference manual to the C# language as of version 1.0 of the .NET Framework. It lists a concise description of language syntax and provides a guide to other areas of the .NET Framework that are of interest to C# programmers.The purpose of this quick reference is to aid readers who need to look up some basic detail of C# syntax or usage. It is not intended to be a tutorial or user guide, and at least a basic familiarity with C# is assumed. If you'd like more in-depth information or a more detailed reference, please see Programming C# by Jesse Liberty and C# in a Nutshell by Drayton, Albahari, and Neward (both O'Reilly, 2002).Identifiers are names programmers choose for their types, methods, variables, etc. An identifier must be a whole word that is essentially made up of Unicode characters starting with a letter or an underscore, and it may not clash with a keyword. As a special case, the@
prefix may be used to avoid a clash with a keyword, but is not considered part of the identifier. For instance, the following two identifiers are equivalent:Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Identifiers and Keywords
- Content preview·Buy reprint rights for this chapterIdentifiers are names programmers choose for their types, methods, variables, etc. An identifier must be a whole word that is essentially made up of Unicode characters starting with a letter or an underscore, and it may not clash with a keyword. As a special case, the
@
prefix may be used to avoid a clash with a keyword, but is not considered part of the identifier. For instance, the following two identifiers are equivalent:C# identifiers are case-sensitive; however, for compatibility with other languages, you should not differentiate public or protected identifiers by case alone.Here is a list of C# keywords:abstract
as
base
bool
break
byte
case
catch
char
checked
class
const
continue
decimal
default
delegate
do
double
else
enum
event
explicit
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Fundamental Elements
- Content preview·Buy reprint rights for this chapterA C# program is best understood in terms of three basic elements:
- Functions
-
Perform an action by executing a series of statements. For example, you may have a function that returns the distance between two points or a function that calculates the average of an array of values. A function is a way of manipulating data.
- Data
-
Values that functions operate on. For example, you may have data holding the coordinates of a point or data holding an array of values. Data always has a particular type.
- Types
-
A set of data members and function members. The function members are used to manipulate the data members. The most common types are classes and structs, which provide a template for creating data. Data is always an instance of a type.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Value and Reference Types
- Content preview·Buy reprint rights for this chapterAll C# types fall into the following categories:
-
Value types (struct, enum)
-
Reference types (class, array, delegate, interface)
The fundamental difference between the two main categories is how they are handled in memory. The following sections explain the essential differences between value types and reference types.Value types directly contain data, such as theint
type (which holds an integer) or thebool
type (which holds atrue
orfalse
value). The key characteristic of a value type is a copy made of the value that is assigned to another value. For example:using System; class Test { static void Main ( ) { int x = 3; int y = x; // assign x to y, y is now a copy of x x++; // increment x to 4 Console.WriteLine (y); // prints 3 } }
Reference types are a little more complex. A reference type defines two separate entities: an object and a reference to that object. This example follows the same pattern as our previous example, except that the variabley
is updated here, whiley
remained unchanged earlier:using System; using System.Text; class Test { static void Main ( ) { StringBuilder x = new StringBuilder ("hello"); StringBuilder y = x; x.Append (" there"); Console.WriteLine (y); // prints "hello there" } }
This is because theStringBuilder
type is a reference type, while theint
type is a value type. When we declared theStringBuilder
variable, we were actually doing two different things, which can be separated into these two lines:StringBuilder x; x = new StringBuilder ("hello");
The first line creates a new variable that can hold a reference to aStringBuilder
object. The second line assigns a newStringBuilder
object to the variable. Let's look at the next line:StringBuilder y = x;
When we assignAdditional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! -
- Predefined Types
- Content preview·Buy reprint rights for this chapterAll of C#'s predefined types alias types found in the
System
namespace. For example, there is only a syntactic difference between these two statements:int i = 5; System.Int32 i = 5;
This table lists the integral types and their features:C# typeSystem typeSizeSignedsbyte
System.SByte
1 byteYesshort
System.Int16
2 bytesYesint
System.Int32
4 bytesYeslong
System.Int64
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Arrays
- Content preview·Buy reprint rights for this chapterArrays allow a group of elements of a particular type to be stored in a contiguous block of memory. An array is specified by placing square brackets after the element type. For example:
int[] nums = new int[2]; nums[0] = 100; nums[1] = 200; char[ ] vowels = new char[ ] {'a','e','i','o','u'}; Console.WriteLine(vowels [1]); // Prints "e"
That last line prints"e"
because array indexes start at 0. To support other languages, .NET can create arrays based on arbitrary start indexes, but all the libraries use zero-based indexing. Once an array is created, its length cannot be changed. However, theSystem.Collection
classes provide dynamically sized arrays, as well as other data structures, such as associative (key/value) arrays.Multidimensional arrays come in two varieties: rectangular and jagged. Rectangular arrays represent an n-dimensional block, while jagged arrays are arrays of arrays. In this example we make use of thefor
loop, which is explained later in Section 1.8. Thefor
loops here simply iterate through each item in the arrays.// rectangular int [,,] matrixR = new int [3, 4, 5]; // creates 1 big // cube // jagged int [ ][ ][ ] matrixJ = new int [3][ ][ ]; for (int i = 0; i < 3; i++) { matrixJ[i] = new int [4][ ]; for (int j = 0; j < 4; j++) matrixJ[i][j] = new int [5]; } // assign an element matrixR [1,1,1] = matrixJ [1][1][1] = 7;
For convenience, local and field declarations may omit the array type when assigning a known value, since the type is specified in the declaration anyway:int[,] array = {{1,2},{3,4}};
Arrays know their own length. For multidimensional array methods, the array'sGetLength
method returns the number of elements for a given dimension, which is from 0 (the outermost) to the array'sAdditional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Variables and Parameters
- Content preview·Buy reprint rights for this chapterA variable represents a typed storage location. A variable can be a local variable, parameter, array element, instance field, or static field.All variables have an associated type, which essentially defines the possible values the variable can have and the operations that can be performed on that variable. C# is strongly typed, which means the set of operations that can be performed on a type are enforced at compile time rather than at runtime. In addition, C# is type-safe, which ensures that a variable can be operated on via the correct type only with the help of runtime checking (except in unsafe blocks).All variables in C# must be assigned a value before they are used. A variable is either explicitly assigned a value or automatically assigned a default value. Automatic assignment occurs for static fields, class instance fields, and array elements not explicitly assigned a value. For example:
using System; class Test { int v; // Constructors that initalize an instance of a Test public Test( ) {} // v will be automatically assigned to // 0 public Test(int a) { // explicitly assign v a value v = a; } static void Main( ) { Test[ ] tests = new Test [2]; // declare array Console.WriteLine(tests[1]); // ok, elements assigned // to null Test t; Console.WriteLine(t); // error, t not assigned before // use } }
The default value for all primitive (or atomic) types is zero:TypeDefault valueNumeric types0
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Expressions and Operators
- Content preview·Buy reprint rights for this chapterAn expression is a sequence of operators and operands that specifies a computation. C# has unary operators, binary operators, and one ternary operator. Complex expressions can be built because an operand may itself be an expression, such as the operand (1 + 2) shown in the following example:
((1 + 2) / 3)
When an expression contains multiple operators, the precedence of the operators controls the order in which the individual operators are evaluated. When the operators are of the same precedence, their associativity determines the order. Binary operators (except for assignment operators) are left-associative; i.e., they are evaluated from left to right. The assignment operators, unary operators, and the conditional operator are right-associative; i.e., they are evaluated from right to left. For example:1 + 2 + 3 * 4
is evaluated as:((1 + 2) + (3 * 4))
because * has a higher precedence than +, and + is a binary operator that is left-associative. You can insert parentheses to change the default order of evaluation. C# overloads operators, which means the same operator can have different meanings for different types.Table 1-2 lists C#'s operators in order of precedence. Operators in the same box have the same precedence, and operators in italic may be overloaded for custom types.Table 1-2: Operator precedence table CategoryOperatorsExamplesPrimaryGrouping:Member access:Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Statements
- Content preview·Buy reprint rights for this chapterExecution in a C# program is specified by a series of statements that execute sequentially in the textual order in which they appear. All statements in a procedural-based language such as C# are executed for their effect. For instance, a statement may assign an expression to a variable, repeatedly execute a list of statements, or jump to another statement.So that multiple statements can be grouped together, zero or more statements may be enclosed in braces to form a statement block.An expression statement evaluates an expression, either assigning its result to a variable or generating side effects (i.e., method invocation,
new
,++
,--
). An expression statement ends in a semicolon. For example:int x = 5 + 6; // assign result x++; // side effect int y = Math.Min(x, 20); // side effect and assign result Math.Min(x, y); // discards result, but ok, there is a // side effect x == y; // error, has no side effect, and does not assign // result
A declaration statement declares a new variable, optionally assigning the result of an expression to that variable. A declaration statement ends in a semicolon:int x = 100; // variable declaration const int y = 110; // constant 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:bool a = true; while(a) { int x = 5; if (x==5) { int y = 7; int x = 2; // error, x already defined } Console.WriteLine(y); // error, y is out of scope }
A constant declaration is like a variable declaration, except that the variable cannot be changed after it has been declared:const double speedOfLight = 2.99792458E08; speedOfLight+=10; // error
C# has many ways to control the flow of program execution conditionally. This section covers the simplest two constructs: theAdditional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Namespaces
- Content preview·Buy reprint rights for this chapterThese are defined in files, organized by namespaces, compiled into a module, then grouped into an assembly. These organizational units are cross-cutting. For example, typically a group of namespaces belong to one assembly, but a single namespace may in fact be spread over multiple assemblies.File organization is almost of no significance to the C# compiler—a whole project could be merged into one .cs file and it would still compile (preprocessor statements are the only exception to this). However, it's generally tidy to have one type in one file, with the filename matching the name of the class and the file's directory matching the name of the class's namespace.A namespace lets you group related types into a hierarchical categorization. Generally, the first name is the name of your organization; it gets more specific from there:
namespace MyCompany.MyProduct.Drawing { class Point {int x, y, z;} delegate void PointInvoker(Point p); }
Section 1.9.2.1: Nesting namespaces
You may also nest namespaces instead of using dots. This example is semantically identical to the previous example:namespace MyCompany { namespace MyProduct { namespace Drawing { class Point {int x, y, z;} delegate void PointInvoker(Point p); } } }
Section 1.9.2.2: Using a type with its fully qualified name
To use thePoint
from another namespace, you may refer to it with its fully qualified name. The namespace that a type is within actually becomes part of the type name:namespace TestProject { class Test { static void Main( ) { MyCompany.MyProduct.Drawing.Point x; } } }
Section 1.9.2.3: The using keyword
Theusing
keyword is a convenient way to avoid using the fully qualified name of types in other namespaces. This example is semantically identical to our previous example:Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Classes
- Content preview·Buy reprint rights for this chapterIn C#, a program is built by defining new types, each with a set of data members and function members. Custom types should form higher-level building blocks that are easy to use and that closely model your problem space.In this example, we simulate an astronaut jumping on different planets, using three classes—
Planet
,Astronaut
, andTest
—to test our simulation.First, let's define thePlanet
class. By convention, we define the data members of the class at the top of the class declaration. There are two data members here, thename
andgravity
fields, which store the name and gravity of a planet. We then define a constructor for the planet. Constructors are function members that allow you to initialize an instance of your class. We initialize the data members with values fed to the parameters of the constructor. Finally, we define two more function members, which are properties that allow us to get the "Name" and "Gravity" of a planet. ThePlanet
class looks like this:using System; class Planet { string name; // field double gravity; // field // constructor public Planet (string n, double g) { name = n; gravity = g; } // property public string Name { get {return name;} } // property public double Gravity { get {return gravity;} } }
Next, we define theAstronaut
class. As with thePlanet
class, we first define our data members. Here an astronaut has two fields: the astronaut's fitness and the current planet the astronaut is on. We then provide a constructor, which initializes the fitness of an astronaut. Next, we define aCurrentPlanet
property that allows us to get or set the planet an astronaut is on. Finally, we define a jump method that outputs how far the astronaut jumps, based on the fitness of the astronaut and the planet he is on.using System; class Astronaut { double fitness; // field Planet currentPlanet; // field // constructor public Astronaut (double f) { fitness = f; } // property public Planet CurrentPlanet { get { return currentPlanet; } set { currentPlanet = value; } } // method public void Jump ( ) { if (currentPlanet == null) Console.WriteLine ("Bye Bye!"); else { double distance = fitness/currentPlanet.Gravity; Console.WriteLine ("Jumped {0} metres on {1}", distance, currentPlanet.Name); } } }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Access Modifiers
- Content preview·Buy reprint rights for this chapterTo promote encapsulation, a type or type member may hide itself from other types or other assemblies by adding one of the following five access modifiers to the declaration:
- public
-
The type or type member is fully accessible. This is the implicit accessibility for enum members (see the later section Section 1.14) and interface members (see the later section Section 1.13).
- internal
-
The type or type member in assembly A is accessible only from within A. This is the default accessibility for nonnested types, and so it may be omitted.
- private
-
The type member in type T is accessible only from within T. This is the default accessibility for class and struct members, and so it may be omitted.
- protected
-
The type member in class C is accessible from within C or from within a class that derives from C.
- protected internal
-
The type member in class C and assembly A is accessible from within C, from within a class that derives from C, or from within A. Note that C# has no concept of protected and internal, whereby "a type member in class C and assembly A is accessible only from within C, or from within a class that both derives from C and is within A."
Note that a type member may be a nested type. Here is an example of using access modifiers:// Assembly1.dll using System; public class A { private int x=5; public void Foo( ) {Console.WriteLine (x);} protected static void Goo( ) {} protected internal class NestedType {} } internal class B { private void Hoo ( ) { A a1 = new A ( ); // ok Console.WriteLine(a1.x); // error, A.x is private A.NestedType n; // ok, A.NestedType is internal A.Goo( ); // error, A's Goo is protected } } // Assembly2.exe (references Assembly1.dll) using System; class C : A { // C defaults to internal static void Main( ) { // Main defaults to private A a1 = new A( ); // ok a1.Foo( ); // ok C.Goo( ); // ok, inherits A's protected static member new A.NestedType( ); // ok, A.NestedType is protected new B( ); // error, Assembly 1's B is internal Console.WriteLine(x); // error, A's x is private } }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Structs
- Content preview·Buy reprint rights for this chapterA struct is similar to a class, with the following major differences:
-
A class is a reference type, while a struct is a value type. Consequently, structs are typically used to express simple types, in which value-type semantics are desirable (e.g., an assignment copies a value rather than a reference).
-
A class fully supports inheritance, whereas a struct can inherit only from an object and is implicitly sealed (in the runtime, structs actually inherit from
System.ValueType
). Both classes and structs can implement interfaces. -
A class can have a destructor, and a struct cannot.
-
A class can define a custom parameterless constructor and initialize instance fields, while a struct cannot. The default parameterless constructor for a struct initializes each field with a default value (effectively zero). If a struct declares a constructor(s), then all of its fields must be assigned in that constructor call.
Here is a simple struct declaration:struct Point { public int x, y; }
To create a struct, you can use thenew
operator, which will initialize all the struct members to their defaults (zero in the case ofx
andy
). If you do not use thenew
operator, you will need to initialize the struct members yourself. You can also use array declaration syntax to create an array of structs:Point p1 = new Point( ); Point p2; p2.x = p2.y = 0; Point[] points = new Point[3];
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! -
- Interfaces
- Content preview·Buy reprint rights for this chapterAn interface is similar to a class, but with the following major differences:
-
An interface provides a specification rather than an implementation for its members. This is similar to a pure abstract class, which consists only of abstract members.
-
A class and struct can implement multiple interfaces, while a class can inherit only from a single class.
-
A struct can implement an interface, but a struct cannot inherit from a class.
Polymorphism is described as the ability to perform the same operations on many types, as long as each type shares a common subset of characteristics. The purpose of an interface is precisely for defining such a set of characteristics.An interface is comprised of a set of the following members:-
Method
-
Property
-
Indexer
-
Event
These members are always implicitly public and implicitly abstract (and therefore virtual and nonstatic).An interface declaration is like a class declaration, but it provides no implementation for its members since all its members are implicitly abstract. These members are intended to be implemented by a class or struct that implements the interface. Here is a very simple interface that defines a single method:public interface IDelete { void Delete( ); }
Classes or structs that implement an interface may be said to "fulfill the contract of the interface." In this example, ourIDelete
interface can be implemented by GUI controls that support the concept of deleting, such as aTextBox
,TreeView
, or your own custom GUI control.public class TextBox : IDelete { public void Delete( ) {...} } public class TreeView : IDelete { public void Delete( ) {...} }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! -
- Enums
- Content preview·Buy reprint rights for this chapterEnums specify a group of named numeric constants:
public enum Direction {North, East, West, South}
Unlike in C, enum members must be used with the enum type name. This resolves naming conflicts and makes code clearer:Direction walls = Direction.East;
By default, enums are assigned integer constants 0, 1, 2, etc. You may optionally specify an alternative numeric type to base your enum and explicitly specify values for each enum member:[Flags] public enum Direction : byte { North=1, East=2, West=4, South=8 } Direction walls = Direction.North | Direction.West; if((walls & Direction.North) != 0) System.Console.WriteLine("Can't go north!");
The[Flags]
attribute is optional and informs the runtime that the values in the enum can be bit-combined and should be decoded accordingly in the debugger or when outputting text to the console. For example:Console.WriteLine(walls); // Displays "North, West" Console.WriteLine((int) walls); // Displays "5"
TheSystem.Enum
type also provides many useful static methods for enums that let you determine the underlying type of an enum, check if a specific value is supported, initialize an enum from a string constant, retrieve a list of the valid values, and other common operations such as conversions. Here is an example of the usage:using System; public enum Toggle : byte { Off=0, On=1 } class Test { static void Main( ) { Type t = Enum.GetUnderlyingType(typeof(Toggle)); Console.WriteLine(t); // Prints "Byte" bool bDimmed = Enum.IsDefined(typeof(Toggle), "Dimmed"); Console.WriteLine(bDimmed); // Prints "False" Toggle tog =(Toggle)Enum.Parse(typeof(Toggle), "On"); Console.WriteLine(Enum.Format(typeof(Toggle), tog, "D")); // Prints "1" Console.WriteLine(tog); // Prints "On" Array oa = Enum.GetValues(typeof(Toggle)); foreach(Toggle toggle in oa) // Prints "On=1, Off=0" Console.WriteLine("{0}={1}", toggle, Enum.Format(typeof(Toggle), toggle, "D")); } }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Delegates
- Content preview·Buy reprint rights for this chapterA delegate is a type defining a method signature, so that delegate instances can hold and invoke a method or list of methods that match its signature. A delegate declaration consists of a name and a method signature. For example:
using System; delegate bool Filter (string s); class Test { static void Main( ) { Filter f = new Filter(FirstHalfOfAlphabet); Display(new String [ ] {"Ant","Lion","Yak"}, f); } static bool FirstHalfOfAlphabet(string s) { return "N".CompareTo(s) > 0; } static void Display(string[ ] names, Filter f) { int count = 0; foreach(string s in names) if(f(s)) // invoke delegate Console.WriteLine("Item {0} is {1}", count++, s); } }
Note that the signature of a delegate method includes its return type. It also allows the use of aparams
modifier in its parameter list, which expands the list of elements that characterize an ordinary method signature. The actual name of the target method is irrelevant to the delegate.Delegates can hold and invoke multiple methods. In this example, we declare a very simple delegate calledMethodInvoker
, which we use to hold and then invoke theFoo
andGoo
methods sequentially. The+=
method creates a new delegate by adding the right delegate operand to the left delegate operand:using System; delegate void MethodInvoker( ); class Test { static void Main( ) { new Test( ); // prints "Foo","Goo" } Test ( ) { MethodInvoker m = null; m += new MethodInvoker(Foo); m += new MethodInvoker(Goo); m( ); } void Foo( ) { Console.WriteLine("Foo"); } void Goo( ) { Console.WriteLine("Goo"); } }
A delegate can also be removed from another delegate using the-=
operator:Test( ) { MethodInvoker m = null; m += new MethodInvoker(Foo); m -= new MethodInvoker(Foo); // m is now null }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Events
- Content preview·Buy reprint rights for this chapterEvent handling is essentially a process in which one object can notify other objects that an event has occurred. This process is largely encapsulated by multicast delegates, which have this ability built in.The .NET Framework provides many event-handling delegates, but you can write your own. For example:
public delegate void MoveEventHandler(object source, MoveEventArgs e);
By convention, the delegate's first parameter denotes the source of the event, and the delegate's second parameter derives fromSystem.EventArgs
and contains data about the event.TheEventArgs
class may be derived from to include information relevant to a particular event:using System; public class MoveEventArgs : EventArgs { public int newPosition; public bool cancel; public MoveEventArgs(int newPosition) { this.newPosition = newPosition; } }
A class or struct can declare an event by applying the event modifier to a delegate field. In this example, the slider class has aPosition
property that fires aMove
event whenever itsPosition
changes:public class Slider { int position; public event MoveEventHandler Move; public int Position { get { return position; } set { if (position != value) { // if position changed if (Move != null) { // if invocation list not // empty MoveEventArgs args = new MoveEventArgs(value); Move(this, args); // fire event if (args.cancel) return; } position = value; } } } }
Theevent
keyword promotes encapsulation by ensuring that only the+=
and-=
operations can be performed on the delegate. Other classes may act on the event, but only theSlider
can invoke the delegate (fire the event) or clear the delegate's invocation list.We are able to act on an event by adding an event handler to it. An event handler is a delegate that wraps the method we want invoked when the event is fired.Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Operator Overloading
- Content preview·Buy reprint rights for this chapterC# lets you overload operators to work with operands that are custom classes or structs using operators. An operator is a static method with the keyword
operator
preceding the operator to overload (instead of a method name), parameters representing the operands, and return types representing the result of an expression. Table 1-3 lists the available overloadable operators.Table 1-3: Overloadable operators +
-
!
~
++
--
*
(binary only)/
%
&
(binary only)|
^
<<
>>
==
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Try Statements and Exceptions
- Content preview·Buy reprint rights for this chapterThe purpose of a
try
statement is to simplify program execution in exceptional circumstances—typically, an error. Atry
statement does two things. First, it lets thecatch
block catch exceptions thrown during thetry
block's execution. Second, it ensures that execution cannot leave thetry
block without first executing thefinally
block. Atry
block must be followed by acatch
block(s), afinally
block, or both. The form of atry
block looks like this:try { ... // exception may be thrown during execution of this // function } catch (ExceptionA ex) { ... // react to exception of type ExceptionA } catch (ExceptionB ex) { ... // react to exception of type ExceptionB } finally { ... // code to always run after try block executes, even if ... // an exception is not thrown }
C# exceptions are objects that contain information representing the occurrence of an exceptional program state. When an exceptional state occurs (e.g., a method receives an illegal value), an exception object may be thrown, and the call-stack is unwound until the exception is caught by an exception-handling block. For example:using System; public class WeightCalculator { public static float CalcBMI (float weightKilos, float metersTall) { if (metersTall < 0 || metersTall > 3) throw new ArgumentException ("Impossible Height", "metersTall"); if (metersTall < 0 || weightKilos > 1000) throw new ArgumentException ("Impossible Weight", "weightKilos"); return weightKilos / (metersTall*metersTall); } } class Test { static void Main ( ) { TestIt ( ); } static void TestIt ( ) { try { float bmi = WeightCalculator.CalcBMI (100, 5); Console.WriteLine(bmi); } catch(ArgumentException ex) { Console.WriteLine(ex); } finally { Console.WriteLine ( "Thanks for running the program"); } Console.Read( ); } }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Attributes
- Content preview·Buy reprint rights for this chapterAttributes are language constructs that can decorate a code element (assemblies, modules, types, members, return values, and parameters) with additional information.In every language, you specify information associated with the types, methods, parameters, and other elements of your program. For example, a type can specify a list of interfaces from which it derives, or a parameter can specify modifiers, such as the
ref
modifier in C#. The limitation of this approach is that you can associate information with code elements using only the predefined constructs that the language provides.Attributes allow programmers to extend the types of information associated with these code elements. For example, serialization in the .NET Framework uses various serialization attributes applied to types and fields to define how these code elements are serialized. This approach is more flexible than requiring the language to have special syntax for serialization.An attribute is defined by a class that inherits (directly or indirectly) from the abstract classSystem.Attribute
. When specifying an attribute to an element, the attribute name is the name of the type. By convention, the derived type name ends inAttribute
, although specifying the suffix is not required when specifying the attribute.In this example, theFoo
class is specified as serializable using theSerializable
attribute:[Serializable] public class Foo {...}
TheSerializable
attribute is actually a type declared in theSystem
namespace, as follows:class SerializableAttribute : Attribute {...}
We could also specify theSerializable
attribute using its fully qualified type name, as follows:[System.SerializableAttribute] public class Foo {...}
The preceding two examples of using theSerializable
attribute are semantically identical.The C# language and the FCL include a number of predefined attributes. For more information about the other attributes included in the FCL and about creating your own attributes, see the "Writing Custom Attributes" topic in the .NET Framework SDK Documentation.Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Unsafe Code and Pointers
- Content preview·Buy reprint rights for this chapterC# supports direct memory manipulation via pointers within blocks of code marked unsafe and compiled with the
/unsafe
compiler option. Pointer types are primarily useful for interop with C APIs, but may also be used for accessing memory outside the managed heap or for performance-critical hotspots.For every value type or pointer type V, there is a corresponding pointer type V*. A pointer instance holds the address of a value. This is considered to be of type V, but pointer types can be (unsafely) cast to any other pointer type. Table 1-4 lists the main pointer operators.Table 1-4: Principal pointer operators OperatorMeaning&
The address-of operator returns a pointer to the address of a value*
The dereference operator returns the value at the address of a pointer->
The pointer-to-member operator is a syntactic shortcut, in whichx->y
is equivalent to(*x).y
By marking a type, type member, or statement block with theunsafe
keyword, you're permitted to use pointer types and perform C++-style pointer operations on memory within that scope. Here is an example of using pointers with a managed object:Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Preprocessor Directives
- Content preview·Buy reprint rights for this chapterPreprocessor directives supply the compiler with additional information about regions of code. The most common preprocessor directives are the conditional directives, which provide a way to include or exclude regions of code from compilation. For example:
#define DEBUG using System; class MyClass { static int x = 5; static void Main( ) { # if DEBUG Console.WriteLine("Testing: x = {0}", x); # endif } }
In this class, the statement inFoo
is compiled as conditionally dependent upon the presence of theDEBUG
symbol. If we remove theDEBUG
symbol, the statement is not compiled. Preprocessor symbols can be defined within a source file (as we have done) and can be passed to the compiler with the/define
: symbol command-line option.The#error
and#warning
symbols prevent accidental misuse of conditional directives by making the compiler generate a warning or error when given an undesirable set of compilation symbols. See Table 1-5 for a list of preprocessor directives and their actions.Table 1-5: Preprocessor directives Preprocessor directiveAction#define
symbolDefines symbol#undef
symbolUndefines symbol#if
symbol[
operatorAdditional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Framework Class Library Overview
- Content preview·Buy reprint rights for this chapterAlmost all the capabilities of the .NET Framework are exposed via a set of managed types known as the Framework Class Library (FCL). Because these types are CLS compliant, they are accessible from almost any .NET language. FCL types are grouped logically by namespace and are exported from a set of assemblies that are part of the .NET platform. Using these types in a C# application requires you to reference the appropriate assembly when compiling (most essential assemblies are referenced by default; see Section1.23 later in this book). For you to work effectively in C# on the .NET platform, it is important to understand the general capabilities in the predefined class library.In this section, we give an overview of the entire FCL (broken down by logical area) and provide references to relevant types and namespaces so that you can explore their details in the .NET Framework SDK on your own.The specific types and namespaces mentioned in this overview are based on the final released version of the .NET Framework.Useful tools for exploring the FCL include the .NET Framework SDK documentation, the Visual Studio .NET documentation, the WinCV.exe class browser, and the ILDasm.exe disassembler.The core types are contained in the
System
namespace. This namespace is the heart of the FCL and contains classes, interfaces, and attributes on which all other types depend. The root of the FCL is the typeObject
, from which all other .NET types derive. Other fundamental types areValueType
(the base type for structs),Enum
(the base type for enums),Convert
(used to convert between base types),Exception
(the base type for all exceptions), and the boxed versions of the predefined value types. Interfaces that are used throughout the FCL (such asICloneable
,IComparable
,IFormattable
, andIConvertible
) are also defined here. Extended types such asAdditional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Namespaces and Assemblies
- Content preview·Buy reprint rights for this chapterTable 1-6 allows you to look up a namespace and determine which assemblies export that namespace. This information is helpful when constructing the appropriate
/reference
:<file list> command-line option for the C# compiler. However, commonly used assemblies are referenced by default.For a complete list of default assemblies, see the global C# response file, csc.rsp , in %SystemRoot%\Microsoft.NET\Framework\VERSION, where VERSION is the version number of the framework (the first release of .NET is v1.0.3705). You can modify csc.rsp to affect all compilations that run on your machine, or you can create a local csc.rsp in your current directory. The local response file is processed after the global one. You can use the/noconfig
switch with csc.exe to disable the local and global csc.rsp files entirely.Table 1-6: Namespace and assembly cross-reference NamespaceDLLsAccessibility
Accessibility.dllEnvDTE
envdte.dllIEHost.Execute
IEExecRemote.dllMicrosoft.CLRAdmin
mscorcfg.dllAdditional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Regular Expressions
- Content preview·Buy reprint rights for this chapterTable 1-7 through Table 1-16 summarize the regular-expression grammar and syntax supported by the regular-expression classes in
System.Text.RegularExpressions
. (For more information, see the ".NET Framework Regular Expressions" topic in the .NET Framework SDK Documentation.) Each of the modifiers and qualifiers in the tables can substantially change the behavior of the matching and searching patterns. For further information on regular expressions, we recommend the definitive Mastering Regular Expressions by Jeffrey E. F. Friedl (O'Reilly, 2002).All the syntax described in the tables should match the Perl5 syntax, with specific exceptions noted.Table 1-7: Character escapes Escape code sequenceMeaningHexadecimal equivalent\a
Bell\u0007
\b
Backspace\u0008
\t
Tab\u0009
\r
Carriage returnAdditional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - Format Specifiers
- Content preview·Buy reprint rights for this chapterTable 1-17 lists the numericformat specifiers supported by the
Format
method on the predefined numeric types.Table 1-17: Numeric format specifiers SpecifierString resultDatatypeC[
n]
$XX,XX.XX
($XX,XXX.XX)
CurrencyD[
n]
[-]XXXXXXX
DecimalE[
n]
ore[
n]
[-]X.XXXXXXE+xxx
[-]X.XXXXXXe+xxx
[-]X.XXXXXXE-xxx
[-]X.XXXXXXe-xxx
ExponentF[
n]
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! - C# Compiler Options
- Content preview·Buy reprint rights for this chapterThe C# compiler, csc.exe, compiles C# sources and incorporates resource files and separately compiled modules. It also allows you to specify conditional compilation options, XML documentation, and path information.
csc [options] files
csc foo.cs /r:bar.dll /win32res:foo.res csc foo.cs /debug /define:TEMP
-
/?
,/help
-
Displays usage information and exits.
-
@
file -
Specifies a response file containing arguments to csc.exe.
-
/addmodule
:file1[;
file2...]
-
Imports metadata from one or more named modules (files with the extension .netmodule). To create a module, use
/target:module
. -
/baseaddress
:addr -
Specifies the base address at which to load DLLs.
-
/bugreport
:file -
Generates a text file that contains a bug report. Use this to report a bug in csc.exe.
-
/checked[+|-]
-
If you specify
/checked+
, causes the runtime to throw an exception when an integer operation results in a value outside the range of the associated datatype. This only affects code that has not been wrapped in a checked or unchecked block of code. If you specify
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing! -
- Essential .NET Tools
- Content preview·Buy reprint rights for this chapterThe .NET Framework SDK contains many useful programming tools. Here, in an alphabetical list, are those we have found most useful or necessary for developing C# applications. Unless otherwise noted, the tools in this list can be found either in the \bin directory of your .NET Framework SDK installation or in the %SystemRoot%\Microsoft.NET\Framework\VERSION directory (replace VERSION with the framework version). Once the .NET Framework is installed, you can access these tools from any directory. To use any of these tools, invoke a Command Prompt window, and enter the name of the desired tool. For a complete list of the available command-line switches for any given tool, enter the tool name (e.g.,
csc
), and press the Return key.- ADepends.exe: assembly dependency list
-
Displays all assemblies on which a given assembly is dependent to load. This is a useful C# program found among the samples in the \Tool Developers Guide directory beneath the .NET Framework or Visual Studio .NET directory tree. You need to install these samples before you can use them, because they are not installed by default.
- Al.exe: assembly linking utility
-
Creates an assembly manifest from the modules and resources files you name. You can also include Win32 resources files. Here's an example:
al /out:c.dll a.netmodule b.netmodule
- CorDbg.exe: runtime debugger
-
General source-level, command-line debug utility for MSIL programs. This is a very useful tool for C# source debugging. The source for cordbg is available in the \Tool Developers Guide directory.
- Csc.exe: C# compiler
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Return to C# Language Pocket Reference
About O'Reilly | Contact | Jobs | Press Room | How to Advertise | Privacy Policy
|
© 2008, O'Reilly Media, Inc. | (707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.