Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
ArrayList
Attributes
BitArray class
Boxing and Unboxing
Class Members
Collection interfaces
CollectionBase classes
Comparer class
Constructors and Destructors
Copy Constructors
Declaring Classes
Delegate
DictionaryBase classes
Event
Exam 70-536 Study Guide: Skill Set 1
Exception classes
Fields and Properties
Generic Lists
Generic Queue
Generic Stack
Generic interfaces
Generic types
Hashtable class
ICloneable
IComparable
IConvertible
IDisposable
IEquatable
IFormattable
INullableValue
Implement .NET Framework interfaces
Interfaces and Abstract Classes
Iterators
Manage a group of associated data using collections
Manage data in a .NET Framework application
Nested Classes
Nullable type
Queue class
Reference types
SortedList class
Stack class
Template:Exam 70-536 Study Guide Skill Set 1-4
TypeForwardedToAttribute
Typecasting
Use events and delegates
Use generic collections
Use specialized collections
Value types
Value vs Reference
const, static and readonly
enum
struct
ArrayList
Description
An ArrayList is an array that can dynamically grow and shrink.
Members
Here are some of the common members of the ArrayList class. For a complete listing see
the MSDN Reference at the bottom of the page.
Properties
Capacity - Gets or sets the number of elements that the ArrayList can contain.
Count - Gets the number of elements contained in an ArrayList object.
IsFixedSize - Gets a value indicating whether a ArrayList object has a fixed size. A collection
with a fixed size does not allow the addition or removal of elements after the collection is
created, but does allow the modification of existing elements.
Item - Gets or sets the element at the specified index.
Methods
Add(value) - Adds an object to the end of the ArrayList.
Yep
Because the ArrayList is untyped, you should use List<T> unless backwards compatibility is
needed.
Code Examples
Using an arraylist to store numbers
// Create a new ArrayList
ArrayList numbers = new ArrayList();
ArrayList Class
Implements the IList interface using an array whose size is dynamically increased as
required.
Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public class ArrayList : IList, ICollection,
IEnumerable, ICloneable
The following code example shows how to create and initialize an ArrayList and how to print
out its values.
vb
Imports System
Imports System.Collections
Imports Microsoft.VisualBasic
Public Class SamplesArrayList
Public Shared Sub Main()
' Creates and initializes a new ArrayList.
Dim myAL As New ArrayList()
myAL.Add("Hello")
myAL.Add("World")
myAL.Add("!")
'Displays the properties and values of the ArrayList.
Console.WriteLine("myAL")
Console.WriteLine(" Count: {0}", myAL.Count)
Console.WriteLine(" Capacity: {0}", myAL.Capacity)
Console.Write(" Values:")
PrintValues(myAL)
End Sub
Public Shared Sub PrintValues(myList As IEnumerable)
Dim obj As [Object]
For Each obj In myList
Console.Write(" {0}", obj)
Next obj
Console.WriteLine()
End Sub 'PrintValues
End Class
/*
This code produces output similar to the following:
myAL
Count: 3
Capacity: f
Values: Hello World !
*/
Attributes
An attribute is a mechanism to add declarative information to code elements (types,
members, assemblies or modules) beyond the usual predefined keywords. They are saved
with the metadata of the object and can be used to describe the code at runtime or to
affect application behavior at run time through the use of reflection.
An attribute must derive from the System.Attribute class, either directly or indirectly. This
means that as well as the numerous predefined attributes that are in the .NET FCL, you can
define your own custom attributes.
Attributes can be placed on almost any target element (though a specific attribute might
restrict the types of declarations on which it is valid). Syntactically, an attribute is specified
by placing the name of the attribute, enclosed in square brackets, in front of the declaration
of the entity to which it applies. For example, a method with the attribute DllImport is
declared like this:
[DllImport("cards.dll")]
public static extern bool cdtInit
(ref int width, ref int height );Where "cards.dll" is the name of the dll that is being
imported into the application and cdtInit is the name of the method within the dll.
Positional parameters
Positional parameters are specified first. Any positional parameters must be specified in a
certain order and cannot be omitted. For example, if we look at the method above, there is
one specified parameter which is the name of the dll file.
Positional parameters are defined in the constructor of the class, so in this instance, the
constructor of the DllImport attribute looks like this:
Named parameters
Named parameters are optional and can be specified in any order after any positional
parameters. These are defined as public properties in the class. If we take a look at a
couple of the properties of the DllImportAttribute class, we can show this in action.
SetLastError - Indicates whether the callee calls the SetLastError Win32 API function before
returning from the attributed method.
EntryPoint - Indicates the name or ordinal of the DLL entry point to be called.
For example, calling the Beep method located in "kernel32.dll" may look like this:
bool aMethod([In][Out]ref double x);And here is an example of combining the same two
attributes:
[SomeAttribute("Hello")]
public string MyMethod(string aString)
{
return aString;
} This sort of situation arises frequently when marshalling. To resolve the ambiguity, C#
has a set of default targets for each kind of declaration, which can be overridden by
explicitly specifying attribute targets.
[Target: attribute list]The table below lists all declarations where attributes are allowed; for
each declaration, the possible targets for attributes on the declaration are listed in the
second column. The targets in bold are the default values.
Predefined .NET
Valid Targets Description
Attribute
Indicates that the compiler can ignore any calls to this method if the
Conditional Method
associated string is defined.
NonSerialized Field
Applies to fields of a class flagged as Serializable; specifies that
these fields won’t be serialized.
STAThread Method (Main) Indicates that the default threading model for an application is STA.
Specifies the nature of the data layout of a class or struct, such as Auto,
StructLayout Class, struct
Explicit, or Sequential.
Implements thread-local storage (TLS)—in other words, the given static field
ThreadStatic Field (static) isn’t shared across multiple threads and each thread has its own copy of the
static field.
Custom attributes
You can create custom attributes to add extra information to your code.
[System.AttributeUsage(System.AttributeTargets.Class |
System.AttributeTargets.Struct)]
public class AuthorAttribute : System.Attribute
{
private string name;
public double version;
public AuthorAttribute(string name)
{
this.name = name;
version = 1.0;
}
} When using the attribute, the code:
AllowMultiple is a named parameter which specifies whether the indicated attribute can be
specified more than once for a given program element. The default value is false. To allow
the above sample to be used more than once, this parameter needs to be set to true.
[System.AttributeUsage(System.AttributeTargets.Class |
System.AttributeTargets.Struct,
AllowMultiple = true) // multiuse attribute
] The sample in the MSDN article can be seen in use thus:
In order to return all of the attributes members, the AuthorAttribute class needs a small
modification to return the positional parameter.
[Author("J.R.R. Tolkein")]
public class FirstClass
{
}
[Author("R. Feist")]
[Author("J. Herbert", version = 2.0)]
[Author("P. Martin", version = 2.1)]
public class SecondClass
{
}
// No Author attribute
public class ThirdClass
{
}
class Program
{
static void Main(string[] args)
{
PrintAuthorInfo(typeof(FirstClass));
PrintAuthorInfo(typeof(SecondClass));
PrintAuthorInfo(typeof(ThirdClass));
}
BitArray class
Description
The BitArray class manages a compact array of bit values. These bit values are boolean in
nature, having the value true (1) or false (0).
Members
Here are some of the common members of the BitArray class. For a complete listing see the
MSDN Reference at the bottom of the page.
Properties
Count - Gets the number of elements contained in the BitArray.
IsReadOnly - Gets a value indicating whether the BitArray is read-only.
Item - Gets or sets the value of the bit at a specific position in the BitArray.
Length - Gets or sets the number of elements in the BitArray.
[edit]Methods
And(BitArray) - Performs the bitwise AND operation on the elements in the current BitArray
against the corresponding elements in the specified BitArray.
CopyTo(Array,index) - Copies the entire BitArray to a compatible one-dimensional Array,
starting at the specified index of the target array.
Get(position) - Gets the value of the bit at a specific position in the BitArray.
Not() - Inverts all the bit values in the current BitArray, so that elements set to true are
changed to false, and elements set to false are changed to true.
Or(BitArray) - Performs the bitwise OR operation on the elements in the current BitArray
against the corresponding elements in the specified BitArray.
Set(position,value) - Sets the bit at a specific position in the BitArray to the specified value.
SetAll(value) - Sets all bits in the BitArray to the specified value.
Xor(BitArray) - Performs the bitwise exclusive OR operation on the elements in the current
BitArrayagainst the corresponding elements in the specified BitArray.
Size and Indexing
The size of a BitArray is set implicitly or explicitly when you create a new one, or by altering
its Length property. If you shorten a BitArray, bits are truncated from the high-order end. If
you lengthen a BitArray, false bits are added to the high-order end.
Elements in a BitArray are accessed using an integer index, which is zero-based. If you try
to index past the end of the BitArray, an ArgumentException is thrown.
Code Examples
Creating BitArrays
BitArray myBitArray = new BitArray( 5 );Creates a BitArray of length 5 with all values set to
false.
BitArray myBitArray = new BitArray( 5, false );Creates a BitArray of length 5 with all values
set to false.
BitArray myBitArray = new BitArray( 5, true );Creates a BitArray of length 5 with all values
set to true.
byte[] myBytes = new byte[5] { 1, 2, 3, 4, 5 };
BitArray myBitArray = new BitArray( myBytes );Creates a BitArray of length 40 with bit
pattern equal to the binary equivalent of each number in the byte array (8 bits per byte).
bool[] myBools = new bool[5] { true, false, true, true, false };
BitArray myBitArray = new BitArray( myBools );Creates a BitArray of length 5 with bit
pattern equal to the bool array.
int[] myInts = new int[5] { 6, 7, 8, 9, 10 };
BitArray myBitArray = new BitArray( myInts );Creates a BitArray of length 160 with bit
pattern equal to the binary equivalent of each number in the int array (32 bits per int).
//setting a value
for (byte x = 0; x < myBits.Count; x++)
{
myBits[x] = (((value >> x) & 0x01) == 0x01) ? true : false;
}This type of code can be done in many convoluted ways. The use of a shift operation, bit
mask operation and short hand if statement simplify this into just 2 easily understandable
lines of code.
BitArray Class
Manages a compact array of bit values, which are represented as Booleans, where true
indicates that the bit is on (1) and false indicates the bit is off (0).
Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
Syntax:
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public sealed class BitArray : ICollection,
IEnumerable, ICloneable
Examples
The following code example shows how to create and initialize a BitArray and how to print
out its values.
using System;
using System.Collections;
public class SamplesBitArray {
Console.WriteLine( "myBA2" );
Console.WriteLine( " Count: {0}", myBA2.Count );
Console.WriteLine( " Length: {0}", myBA2.Length );
Console.WriteLine( " Values:" );
PrintValues( myBA2, 8 );
Console.WriteLine( "myBA3" );
Console.WriteLine( " Count: {0}", myBA3.Count );
Console.WriteLine( " Length: {0}", myBA3.Length );
Console.WriteLine( " Values:" );
PrintValues( myBA3, 8 );
Console.WriteLine( "myBA4" );
Console.WriteLine( " Count: {0}", myBA4.Count );
Console.WriteLine( " Length: {0}", myBA4.Length );
Console.WriteLine( " Values:" );
PrintValues( myBA4, 8 );
Console.WriteLine( "myBA5" );
Console.WriteLine( " Count: {0}", myBA5.Count );
Console.WriteLine( " Length: {0}", myBA5.Length );
Console.WriteLine( " Values:" );
PrintValues( myBA5, 8 );
}
}
/*
This code produces the following output.
myBA1
Count: 5
Length: 5
Values:
False False False False False
myBA2
Count: 5
Length: 5
Values:
False False False False False
myBA3
Count: 40
Length: 40
Values:
True False False False False False False False
False True False False False False False False
True True False False False False False False
False False True False False False False False
True False True False False False False False
myBA4
Count: 5
Length: 5
Values:
True False True True False
myBA5
Count: 160
Length: 160
Values:
False True True False False False False False
False False False False False False False False
False False False False False False False False
False False False False False False False False
True True True False False False False False
False False False False False False False False
False False False False False False False False
False False False False False False False False
False False False True False False False False
False False False False False False False False
False False False False False False False False
False False False False False False False False
True False False True False False False False
False False False False False False False False
False False False False False False False False
False False False False False False False False
False True False True False False False False
False False False False False False False False
False False False False False False False False
False False False False False False False False
*/
Inheritance Hierarchy
System..::.Object
System.Collections..::.BitArray
Thread Safety
Public static (Shared in Visual Basic) members of this type are thread safe. Any instance
members are not guaranteed to be thread safe.
This implementation does not provide a synchronized (thread safe) wrapper for a BitArray.
Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a
collection is synchronized, other threads can still modify the collection, which causes the
enumerator to throw an exception. To guarantee thread safety during enumeration, you can
either lock the collection during the entire enumeration or catch the exceptions resulting
from changes made by other threads.
BitArray Members
Manages a compact array of bit values, which are represented as Booleans, where true
indicates that the bit is on (1) and false indicates the bit is off (0).
The BitArray type exposes the following members.
Properties
Name Description
Count Gets the number of elements contained in the BitArray.
IsReadOnly Gets a value indicating whether the BitArray is read-only.
IsSynchronized Gets a value indicating whether access to the BitArray is synchronized
(thread safe).
Item Gets or sets the value of the bit at a specific position in the BitArray.
Length Gets or sets the number of elements in the BitArray.
SyncRoot Gets an object that can be used to synchronize access to the BitArray.
Unboxing is not type safe. It requires a cast because the compiler cannot determine the
type of the object. If the object is not the correct type, it will cause an exception during
the cast operation.
Large numbers of boxing and unboxing operations can become a performance problem. It
should be avoided if possible. In particular, Generic types do not depend on boxing
operations and they should be used whenever possible. Also, generic types maintain type
safety.
Class Members
Once a class is created it must be populated with data and methods in order to make it
useful as a programming construct. The data and methods which act upon the data are
referred to as members.
Members
There are several types of members that a class can have. These are:
Fields - instances of objects that are considered part of a class, normally holding class
data.
Properties - methods on a class that are accessed as if they were fields on that class. A
property can provide protection for a class field to keep it from being changed without the
object's knowledge. For a more detailed understanding see Fields and Properties.
Methods - these define the actions that a class can perform by actioning a series of
statements. Methods can take parameters that provide input data, and can return output
data through parameters. Methods can also return a value directly, without using a
parameter.
Events - a way of providing notifications about occurrences, such as button clicks or the
successful completion of a method, to other objects. Events are defined and triggered
using delegates. (See the 70-536 entry for Events and check out the article by Jeff Sudeth
and read the sample chapter "Delegates and Events" by Jesse Liberty).
Delegates - a type safe container of one or more function pointers. (See the 70-536 entry
for Delegates and check out the article by Jeff Sudeth).
Operators - these are terms or symbols such as +, *, <, and so on that perform
operations on operands. Operators can be redefined to perform operations on custom data
types.
Indexers - these allow an object to be indexed in a manner similar to arrays.
Constructors - methods that are called when the object is first created. They are often
used to initialize the object's data.
Destructors - methods that are called by the runtime execution engine when the object is
about to be removed from memory. They are generally used to make sure that any
resources which need to be released are handled appropriately.
Constants - data members that are known at compile time.
Modifiers
Each type of modifier may or may not be available to a member. The modifiers may
include:
abstract - indicates that a class is intended only to be a base class of other classes.
extern - used to declare a method that is implemented externally (as in a DLL file).
readonly - fields that are read-only and are initialized at declaration or in a constructor.
sealed - overrides a method in a base class, but itself cannot be overridden further in any
derived class.
static – a member that doesn't belong to an instance of the class, but belongs to the class
itself.
virtual - used to modify a method, property, indexer or event declaration, and allow it to
be overridden in a derived class.
volatile - fields that are modifiable by the environment, a separate thread, or hardware.
Accessibility
public - any item in the current assembly or any assembly that references the class, can
access this member.
protected - access is limited to the containing class or types derived from the containing
class.
internal - any item in the current assembly can access this member.
protected internal - access is limited to the current assembly or types derived from the
containing class.
Classes and structs have members that represent their data and behavior. A class's
members include all the members declared in the class, along with all members (except
constructors and destructors) declared in all classes in its inheritance hierarchy. Private
members in base classes are inherited but are not accessible from derived classes.
The following table lists the kinds of members a class or struct may contain:
Member Description
Fields Fields are variables declared at class scope. A field may be a built-in
numeric type or an instance of another class. For example, a calendar
class may have a field that contains the current date.
Constants Constants are fields or properties whose value is set at compile time and
cannot be changed.
Properties Properties are methods on a class that are accessed as if they were
fields on that class. A property can provide protection for a class field to
keep it from being changed without the knowledge of the object.
Methods Methods define the actions that a class can perform. Methods can take
parameters that provide input data, and can return output data through
parameters. Methods can also return a value directly, without using a
parameter.
Events Events provide notifications about occurrences, such as button clicks or
the successful completion of a method, to other objects. Events are
defined and triggered by using delegates. For more information, see
Events and Delegates.
Operators Overloaded operators are considered class members. When you
overload an operator, you define it as a public static method in a class.
The predefined operators (+, *, <, and so on) are not considered
members. For more information, see Overloadable Operators (C#
Programming Guide).
Indexers Indexers enable an object to be indexed in a manner similar to arrays.
Constructors Constructors are methods that are called when the object is first
created. They are often used to initialize the data of an object.
Destructors Destructors are used very rarely in C#. They are methods that are
called by the runtime execution engine when the object is about to be
removed from memory. They are generally used to make sure that any
resources which must be released are handled appropriately.
Nested Types Nested types are types declared within another type. Nested types are
often used to describe objects that are used only by the types that
contain them.
abstract
The abstract modifier indicates that the thing being modified has a missing or incomplete
implementation. The abstract modifier can be used with classes, methods, properties,
indexers, and events. Use the abstract modifier in a class declaration to indicate that a
class is intended only to be a base class of other classes. Members marked as abstract, or
included in an abstract class, must be implemented by classes that derive from the
abstract class.
Example
abstract class ShapesClass
{
abstract public int Area();
}
class Square : ShapesClass
{
int side = 0;
public Square(int n)
{
side = n;
}
// Area method is required to avoid
// a compile-time error.
public override int Area()
{
return side * side;
}
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
}
// Output: Area of the square = 144
It is not possible to modify an abstract class with the sealed (C# Reference) modifier
because the two modifers have opposite meanings. The sealed modifier prevents a class
from being inherited and the abstract modifier requires a class to be inherited.
A non-abstract class derived from an abstract class must include actual implementations
of all inherited abstract methods and accessors.
Use the abstract modifier in a method or property declaration to indicate that the method
or property does not contain implementation.
Abstract properties behave like abstract methods, except for the differences in declaration
and invocation syntax.
For more information about abstract classes, see Abstract and Sealed Classes and Class
Members (C# Programming Guide) and Abstract Class Design.
An abstract class that implements an interface might map the interface methods onto
abstract methods. For example:
C#
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
In this example, the class DerivedClass is derived from an abstract class BaseClass. The
abstract class contains an abstract method, AbstractMethod, and two abstract properties,
X and Y.
[DllImport("avifil32.dll")]
private static extern void AVIFileInit();
The extern keyword can also define an external assembly alias, which makes it possible to
reference different versions of the same component from within a single assembly.
It is an error to use the abstract (C# Reference) and extern modifiers together to modify
the same member. Using the extern modifier means that the method is implemented
outside the C# code, whereas using the abstract modifier means that the method
implementation is not provided in the class.
Example:
In this example, the program receives a string from the user and displays it inside a
message box. The program uses the MessageBox method imported from the User32.dll
library.
//using System.Runtime.InteropServices;
class ExternTest
{
[DllImport("User32.dll", CharSet=CharSet.Unicode)]
public static extern int MessageBox(int h, string m, string c, int type);
}
This example creates a DLL from a C program that is invoked from within the C# program
in the next example.
// cmdll.c
// Compile with: /LD
int __declspec(dllexport) SampleMethod(int i)
{
return i*10;
}
This example uses two files, CM.cs and Cmdll.c, to demonstrate extern. The C file is the
external DLL created in Example 2 that is invoked from within the C# program.
// cm.cs
using System;
using System.Runtime.InteropServices;
public class MainClass
{
[DllImport("Cmdll.dll")]
public static extern int SampleMethod(int x);
Remarks
To build the project:
cl /LD Cmdll.c
csc CM.cs
This will create the executable file CM.exe. When you run this program, SampleMethod
will pass the value 5 to the DLL file, which returns the value multiplied by 10.
Note:
The extern keyword can also define an external assembly alias, which makes it possible to
reference different versions of the same component from within a single assembly. For
more information, see extern alias (C# Reference).
It is an error to use the abstract (C# Reference) and extern modifiers together to modify
the same member. Using the extern modifier means that the method is implemented
outside the C# code, whereas using the abstract modifier means that the method
implementation is not provided in the class.
Note:
The extern keyword has more limited uses than in C++. To compare with the C++
keyword, see Using extern to Specify Linkage in the C++ Language Reference.
Example
In this example, the program receives a string from the user and displays it inside a
message box. The program uses the MessageBox method imported from the User32.dll
library.
//using System.Runtime.InteropServices;
class ExternTest
{
[DllImport("User32.dll", CharSet=CharSet.Unicode)]
public static extern int MessageBox(int h, string m, string c, int type);
This example creates a DLL from a C program that is invoked from within the C# program
in the next example.
// cmdll.c
// Compile with: /LD
int __declspec(dllexport) SampleMethod(int i)
{
return i*10;
}
This example uses two files, CM.cs and Cmdll.c, to demonstrate extern. The C file is the
external DLL created in Example 2 that is invoked from within the C# program.
// cm.cs
using System;
using System.Runtime.InteropServices;
public class MainClass
{
[DllImport("Cmdll.dll")]
public static extern int SampleMethod(int x);
cl /LD Cmdll.c
csc CM.cs
This will create the executable file CM.exe. When you run this program, SampleMethod
will pass the value 5 to the DLL file, which returns the value multiplied by 10.
When used as a modifier, the new keyword explicitly hides a member inherited from a
base class. When you hide an inherited member, the derived version of the member
replaces the base-class version. Although you can hide members without the use of the
new modifier, the result is a warning. If you use new to explicitly hide a member, it
suppresses this warning and documents the fact that the derived version is intended as a
replacement.
To hide an inherited member, declare it in the derived class by using the same name, and
modify it with the new modifier. For example:
A constant, field, property, or type introduced in a class or struct hides all base class
members with the same name.
A method introduced in a class or struct hides properties, fields, and types, with the same
name, in the base class. It also hides all base class methods with the same signature.
An indexer introduced in a class or struct hides all base class indexers with the same
signature.
It is an error to use both new and override on the same member because the two
modifiers have mutually exclusive meanings. The new modifier creates a new member
with the same name and causes the original member to become hidden. The override
modifier extends the implementation for an inherited member.
Using the new modifier in a declaration that does not hide an inherited member generates
a warning.
Example
In this example, a base class, BaseC, and a derived class, DerivedC, use the same field
name x, which hides the value of the inherited field. The example demonstrates the use of
the new modifier. It also demonstrates how to access the hidden members of the base
class by using their fully qualified names.
In this example, a nested class hides a class that has the same name in the base class.
The example demonstrates how to use the new modifier to eliminate the warning message
and how to access the hidden class members by using their fully qualified names.
Console.WriteLine(c1.x);
Console.WriteLine(c2.x);
}
}
/*
Output:
100
200
*/
If you remove the new modifier, the program will still compile and run, but you will get
the following warning:
Copy Code
The keyword new is required on 'MyDerivedC.x' because it hides inherited member
'MyBaseC.x'.
You can also use the new modifier to modify a nested type if the nested type is hiding
another type, as demonstrated in the following example.
When used as a modifier, the new keyword explicitly hides a member inherited from a
base class. When you hide an inherited member, the derived version of the member
replaces the base-class version. Although you can hide members without the use of the
new modifier, the result is a warning. If you use new to explicitly hide a member, it
suppresses this warning and documents the fact that the derived version is intended as a
replacement.
To hide an inherited member, declare it in the derived class by using the same name, and
modify it with the new modifier. For example:
A constant, field, property, or type introduced in a class or struct hides all base class
members with the same name.
A method introduced in a class or struct hides properties, fields, and types, with the same
name, in the base class. It also hides all base class methods with the same signature.
An indexer introduced in a class or struct hides all base class indexers with the same
signature.
It is an error to use both new and override on the same member because the two
modifiers have mutually exclusive meanings. The new modifier creates a new member
with the same name and causes the original member to become hidden. The override
modifier extends the implementation for an inherited member.
Using the new modifier in a declaration that does not hide an inherited member generates
a warning.
Example
In this example, a base class, BaseC, and a derived class, DerivedC, use the same field
name x, which hides the value of the inherited field. The example demonstrates the use of
the new modifier. It also demonstrates how to access the hidden members of the base
class by using their fully qualified names.
In this example, a nested class hides a class that has the same name in the base class.
The example demonstrates how to use the new modifier to eliminate the warning message
and how to access the hidden class members by using their fully qualified names.
If you remove the new modifier, the program will still compile and run, but you will get
the following warning:
Example
In this example, the Square class must provide an overridden implementation of Area
because Area is inherited from the abstract ShapesClass:
public Square(int n)
{
side = n;
}
// Area method is required to avoid
// a compile-time error.
public override int Area()
{
return side * side;
}
static void Main()
{
Square sq = new Square(12);
Console.WriteLine("Area of the square = {0}", sq.Area());
}
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
}
// Output: Area of the square = 144
You cannot override a non-virtual or static method. The overridden base method must be
virtual, abstract, or override.
An override declaration cannot change the accessibility of the virtual method. Both the
override method and the virtual method must have the same access level modifier.
You cannot use the new, static, virtual, or abstract modifiers to modify an override
method.
An overriding property declaration must specify exactly the same access modifier, type,
and name as the inherited property, and the overridden property must be virtual,
abstract, or override.
For more information about how to use the override keyword, see Versioning with the
Override and New Keywords (C# Programming Guide) and Knowing when to use Override
and New Keywords.
This example defines a base class named Employee, and a derived class named
SalesEmployee. The SalesEmployee class includes an extra property, salesbonus, and
overrides the method CalculatePay in order to take it into account.
class TestOverride
{
public class Employee
{
public string name;
The readonly keyword is a modifier that you can use on fields. When a field declaration
includes a readonly modifier, assignments to the fields introduced by the declaration can
only occur as part of the declaration or in a constructor in the same class.
Example
In this example, the value of the field year cannot be changed in the method ChangeYear,
even though it is assigned a value in the class constructor:
class Age
{
readonly int _year;
Age(int year)
{
_year = year;
}
void ChangeYear()
{
//_year = 1967; // Compile error if uncommented.
}
}
You can assign a value to a readonly field only in the following contexts:
Note:
The readonly keyword is different from the const keyword. A const field can only be
initialized at the declaration of the field. A readonly field can be initialized either at the
declaration or in a constructor. Therefore, readonly fields can have different values
depending on the constructor used. Also, while a const field is a compile-time constant,
the readonly field can be used for runtime constants as in the following example:
public SampleClass()
{
// Initialize a readonly instance field
z = 24;
}
Which is the same error you get when you attempt to assign a value to a constant?
sealed
When applied to a class, the sealed modifier prevents other classes from inheriting from it.
In the following example, class B inherits from class A, but no class can inherit from class
B.
class A {}
sealed class B : A {}
You can also use the sealed modifier on a method or property that overrides a virtual
method or property in a base class. This enables you to allow classes to derive from your
class and prevent them from overriding specific virtual methods or properties.
Example
In the following example, Z inherits from Y but Z cannot override the virtual function F
that is declared in X and sealed in Y.
class X
{
protected virtual void F() { Console.WriteLine("X.F"); }
protected virtual void F2() { Console.WriteLine("X.F2"); }
}
class Y : X
{
sealed protected override void F() { Console.WriteLine("Y.F"); }
protected override void F2() { Console.WriteLine("X.F3"); }
}
class Z : Y
{
// Attempting to override F causes compiler error CS0239.
// protected override void F() { Console.WriteLine("C.F"); }
// Overriding F2 is allowed.
protected override void F2() { Console.WriteLine("Z.F2"); }
}
When you define new methods or properties in a class, you can prevent deriving classes
from overriding them by not declaring them as virtual.
It is an error to use the abstract modifier with a sealed class, because an abstract class
must be inherited by a class that provides an implementation of the abstract methods or
properties.
When applied to a method or property, the sealed modifier must always be used with
override.
class SealedTest2
{
static void Main()
{
SealedClass sc = new SealedClass();
sc.x = 110;
sc.y = 150;
Console.WriteLine("x = {0}, y = {1}", sc.x, sc.y);
}
}
// Output: x = 110, y = 150
In the previous example, you might try to inherit from the sealed class by using the
following statement:
Example
The following class is declared as static and contains only static methods:
To refer to the static member x, use the fully qualified name (unless it is accessible from
the same scope):
MyBaseC.MyStruct.x
While an instance of a class contains a separate copy of all instance fields of the class,
there is only one copy of each static field.
If the static keyword is applied to a class, all the members of the class must be static.
Classes and static classes may have static constructors. Static constructors are called at
some point between when the program starts and the class is instantiated.
Note:
The static keyword has more limited uses than in C++. To compare with the C++
keyword, see Static (C++).
This example reads the name and ID of a new employee, increments the employee
counter by one, and displays the information for the new employee and the new number
of employees. For simplicity, this program reads the current number of employees from
the keyboard. In a real application, this information should be read from a file.
public Employee4()
{
}
This example shows that although you can initialize a static field by using another static
field not yet declared, the results will be undefined until you explicitly assign a value to
the static field.
class Test
{
static int x = y;
static int y = 5;
Test.x = 99;
Console.WriteLine(Test.x);
}
}
/*
Output:
0
5
99
*/
The virtual keyword is used to modify a method, property, indexer, or event declaration
and allow for it to be overridden in a derived class. For example, this method can be
overridden by any class that inherits it:
Remarks
When a virtual method is invoked, the run-time type of the object is checked for an
overriding member. The overriding member in the most derived class is called, which
might be the original member, if no derived class has overridden the member.
You cannot use the virtual modifier with the static, abstract, private, or override modifiers.
The following example shows a virtual property:
class MyBaseClass
{
// virtual auto-implemented property. Overrides can only
// provide specialized behavior if they implement get and set accessors.
public virtual string Name { get; set; }
Virtual properties behave like abstract methods, except for the differences in declaration
and invocation syntax.
Example
In this example, the Dimensions class contains the two coordinates x, y, and the Area()
virtual method. Different shape classes such as Circle, Cylinder, and Sphere inherit the
Dimensions class, and the surface area is calculated for each figure. Each derived class
has it own override implementation of Area(). The program calculates and displays the
appropriate area for each figure by invoking the appropriate implementation of Area()
according to the object associated with the method.
Notice that the inherited classes Circle, Sphere, and Cylinder are all using constructors
that initialize the base class, for example:
public Cylinder(double r, double h): base(r, h) {}
This is similar to the C++ initialization list.
class TestClass
{
public class Dimensions
{
public const double PI = Math.PI;
protected double x, y;
public Dimensions()
{
}
public Dimensions(double x, double y)
{
this.x = x;
this.y = y;
}
The volatile keyword indicates that a field might be modified by multiple threads that are
executing at the same time. Fields that are declared volatile are not subject to compiler
optimizations that assume access by a single thread. This ensures that the most up-to-
date value is present in the field at all times.
The volatile modifier is usually used for a field that is accessed by multiple threads without
using the lock statement to serialize access. See How to: Create and Terminate Threads
(C# Programming Guide) for an example of volatile in a multi-threaded scenario.
Reference types.
Pointer types (in an unsafe context). Note that although the pointer itself can be volatile,
the object that it points to cannot. In other words, you cannot declare a "pointer to
volatile."
Integral types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.
The volatile keyword can only be applied to fields of a class or struct. Local variables
cannot be declared volatile.
Example
The following example shows how to declare a public field variable as volatile.
class VolatileTest
{
public volatile int i;
Collection interfaces
As the name implies, a collection interface is an interface that provides the contract for a
specific collection.
ICollection
ICollection extends IEnumerable. It provides size and synchronization members in
addition to enumeration.
IList
IList extends ICollection. It allows access to the items of a collection by their index.
IDictionary
IDictionary extends ICollection. It allows access to the items of a collection by their key.
IComparer
Allows custom comparison for the purposes of sorting and ordering.
IEqualityComparer
Allows custom equality comparisons for collections that depend on equality but not order
(like Hashtable)
IKeyComparer
Replaced by IEqualityComparer since .NET 2.0 beta 2
IHashCodeProvider
Replaced by IEqualityComparer since .NET 2.0 beta 2
IEnumerable
IEnumerable allows a class to be enumerated using an enumerator. A class should inherit
from IEnumerable in order to provide an enumerator through the GetEnumerator()
method.
The foreach automatically calls GetEnumerator at the beginning of the loop and then uses
that enumerator to go through the loop.
IEnumerator
An IEnumerator iterates over each item in a collection. It allows access to the current item
and the ability to proceed to the next item. The foreach loop uses an enumerator to go
through each item.
IDictionaryEnumerator
A IDictionaryEnumerator extends IEnumerator. It also adds support for accessing the key
and value of the current item.
CollectionBase Class
Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class CollectionBase : IList,
ICollection, IEnumerable
Remarks
A CollectionBase instance is always modifiable. See ReadOnlyCollectionBase for a read-
only version of this class.
The capacity of a CollectionBase is the number of elements the CollectionBase can hold.
As elements are added to a CollectionBase, the capacity is automatically increased as
required through reallocation. The capacity can be decreased by setting the Capacity
property explicitly.
Notes to Implementers:
This base class is provided to make it easier for implementers to create a strongly typed
custom collection. Implementers are encouraged to extend this base class instead of
creating their own.
Examples
The following code example implements the CollectionBase class and uses that
implementation to create a collection of Int16 objects.
using System;
using System.Collections;
protected override void OnSet( int index, Object oldValue, Object newValue ) {
// Insert additional code to be run only when setting values.
}
// Display the contents of the collection using foreach. This is the preferred method.
Console.WriteLine( "Contents of the collection (using foreach):" );
PrintValues1( myI16 );
// Display the contents of the collection using the Count property and the Item
property.
Console.WriteLine( "Initial contents of the collection (using Count and Item):" );
PrintIndexAndValues( myI16 );
// Display the contents of the collection using the Count property and the Item
property.
Console.WriteLine( "Contents of the collection after removing the element 2:" );
PrintIndexAndValues( myI16 );
}
// Uses the foreach statement which hides the complexity of the enumerator.
// NOTE: The foreach statement is the preferred way of enumerating the contents of a
collection.
public static void PrintValues1( Int16Collection myCol ) {
foreach ( Int16 i16 in myCol )
Console.WriteLine( " {0}", i16 );
Console.WriteLine();
}
/*
This code produces the following output.
Contains 3: True
2 is at index 1.
*/
ReadOnlyCollectionBase Class
Provides the abstract base class for a strongly typed non-generic read-only collection.
Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class ReadOnlyCollectionBase : ICollection,
IEnumerable
Remarks
A ReadOnlyCollectionBase instance is always read-only. See CollectionBase for a
modifiable version of this class.
Notes to Implementers:
This base class is provided to make it easier for implementers to create a strongly typed
read-only custom collection. Implementers are encouraged to extend this base class
instead of creating their own. Members of this base class are protected and are intended
to be used through a derived class only.
This class makes the underlying collection available through the InnerList property, which
is intended for use only by classes that are derived directly from ReadOnlyCollectionBase.
The derived class must ensure that its own users cannot modify the underlying collection.
Examples
The following code example implements the ReadOnlyCollectionBase class.
using System;
using System.Collections;
// Create an ArrayList.
ArrayList myAL = new ArrayList();
myAL.Add( "red" );
myAL.Add( "blue" );
myAL.Add( "yellow" );
myAL.Add( "green" );
myAL.Add( "orange" );
myAL.Add( "purple" );
// Display the contents of the collection using foreach. This is the preferred method.
Console.WriteLine( "Contents of the collection (using foreach):" );
PrintValues1( myCol );
// Display the contents of the collection using the Count property and the Item
property.
Console.WriteLine( "Contents of the collection (using Count and Item):" );
PrintIndexAndValues( myCol );
// Uses the foreach statement which hides the complexity of the enumerator.
// NOTE: The foreach statement is the preferred way of enumerating the contents of a
collection.
public static void PrintValues1( ROCollection myCol ) {
foreach ( Object obj in myCol )
Console.WriteLine( " {0}", obj );
Console.WriteLine();
}
/*
This code produces the following output.
*/
Comparer class
You must implement the IComparer interface if you want to provide a custom comparison
method in your code:
Then you can use it as parameter invoking the Sort method for any collection you have:
myList.Sort(new MyCustomComparer());
IComparer Interface
Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
Syntax
C#
[ComVisibleAttribute(true)]
public interface IComparer
Remarks
This interface is used in conjunction with the Array..::.Sort and Array..::.BinarySearch
methods. It provides a way to customize the sort order of a collection.
The default implementation of this interface is the Comparer class. For the generic version
of this interface, see System.Collections.Generic..::.IComparer<(Of <(T>)>).
Examples
The following code example demonstrates the use of the IComparer interface to sort an
ArrayList object. In this example, the IComparer interface is implemented using the
CaseInsensitiveComparer class to reverse the order of the contents of the ArrayList.
Visual Basic
Imports System
Imports System.Collections
Imports Microsoft.VisualBasic
' Sorts the values of the ArrayList using the default comparer.
myAL.Sort()
Console.WriteLine("After sorting with the default comparer:")
PrintIndexAndValues(myAL)
' Sorts the values of the ArrayList using the reverse case-insensitive comparer.
Dim myComparer = New myReverserClass()
myAL.Sort(myComparer)
Console.WriteLine("After sorting with the reverse case-insensitive comparer:")
PrintIndexAndValues(myAL)
C#
using System;
using System.Collections;
/*
This code produces the following output.
The ArrayList initially contains the following values:
[0]: The
[1]: quick
[2]: brown
[3]: fox
[4]: jumps
[5]: over
[6]: the
[7]: lazy
[8]: dog
Remarks
This interface is used in conjunction with the Array..::.Sort and Array..::.BinarySearch
methods. It provides a way to customize the sort order of a collection.
The default implementation of this interface is the Comparer class. For the generic version
of this interface, see System.Collections.Generic..::.IComparer<(Of <(T>)>).
Examples
The following code example demonstrates the use of the IComparer interface to sort an
ArrayList object. In this example, the IComparer interface is implemented using the
CaseInsensitiveComparer class to reverse the order of the contents of the ArrayList.
Visual Basic
Imports System
Imports System.Collections
Imports Microsoft.VisualBasic
' Sorts the values of the ArrayList using the default comparer.
myAL.Sort()
Console.WriteLine("After sorting with the default comparer:")
PrintIndexAndValues(myAL)
' Sorts the values of the ArrayList using the reverse case-insensitive comparer.
Dim myComparer = New myReverserClass()
myAL.Sort(myComparer)
Console.WriteLine("After sorting with the reverse case-insensitive comparer:")
PrintIndexAndValues(myAL)
C#
using System;
using System.Collections;
// Sorts the values of the ArrayList using the reverse case-insensitive comparer.
IComparer myComparer = new myReverserClass();
myAL.Sort( myComparer );
Console.WriteLine( "After sorting with the reverse case-insensitive comparer:" );
PrintIndexAndValues( myAL );
/*
This code produces the following output.
The ArrayList initially contains the following values:
[0]: The
[1]: quick
[2]: brown
[3]: fox
[4]: jumps
[5]: over
[6]: the
[7]: lazy
[8]: dog
Constructors
When a class is declared as in the following code, we only say that we want to have an
instance of the class in our program. We have not yet created the class, only that we have
allocated some program memory.
Car FordCapri;To do this we must instantiate an instance of the class, this is done using
the new keyword, as in the following code:
Car FordCapri = new Car();You can see that after the new keyword we called a method
with the same name as the class. This is called its constructor. A constructor is a method
that is invoked upon instantiation of a class, known as "instance constructors". An
instance constructor is a member that implements the actions required to initialize an
instance of a class.
The constructor_name of a constructor must be the same as the name of the class.
A constructor can take zero or more arguments as parameters. A constructor with zero
arguments (that is no-arguments) is known as a default constructor. A class can have
more than one constructor, by giving each constructor a different set of parameters. This
gives the user the ability to initialise the object in more than one way.
The constructor body can be used to initialise the object into a known starting state.
In, general, a constructor’s access modifier is public, this is because the class that is
creating an instance of this class, needs to be able to access the constructor of the class.
public Car()
{
...
}
Static constructors
A static constructor is used to initialize any static data members. It is called automatically
before the first instance is created or any static members are referenced. A static
constructor does not take access modifiers or have parameters and therefore cannot be
called using the new keyword.
Destructors
Each class also requires a destructor, this is the code that is called to clean up the object
when it has been finished with. However, if you do not provide one, then the Garbage
Collector will deal with freeing up the memory for you. Any object that you create in the
class, should be deleted from the class as a general rule of thumb.
A destructor is defined pretty much in the same way as a constructor, but has a tilde (~)
in front of the method name.
public ~Car()
{
...
}Destructors have the following properties:
Note
Empty destructors should not be used. When a class contains a destructor, an entry is
created in the Finalize queue. When the destructor is called, the garbage collector is
invoked to process the queue. If the destructor is empty, this simply results in a needless
loss of performance.
You should only create a destructor if it is really necessary. Otherwise let the memory
management clean up behind you.
Destructors
Remarks
Destructors cannot be defined in structs. They are only used with classes.
For example, the following is a declaration of a destructor for the class Car:
class Car
{
~Car() // destructor
{
// cleanup statements...
}
}
The destructor implicitly calls Finalize on the base class of the object. Therefore, the
previous destructor code is implicitly translated to the following code:
Note:
Empty destructors should not be used. When a class contains a destructor, an entry is
created in the Finalize queue. When the destructor is called, the garbage collector is
invoked to process the queue. If the destructor is empty, this just causes a needless loss
of performance.
The programmer has no control over when the destructor is called because this is
determined by the garbage collector. The garbage collector checks for objects that are no
longer being used by the application. If it considers an object eligible for destruction, it
calls the destructor (if any) and reclaims the memory used to store the object.
Destructors are also called when the program exits.
It is possible to force garbage collection by calling Collect, but most of the time, this
should be avoided because it may create performance issues.
For more details about cleaning up resources, see the following topics:
C#
class First
{
~First()
{
System.Diagnostics.Trace.WriteLine("First's destructor is called.");
}
}
class TestDestructors
{
static void Main()
{
Third t = new Third();
}
}
/* Output (to VS Output Window):
Third's destructor is called.
Second's destructor is called.
First's destructor is called.
*/
Instance Constructors
Instance constructors are used to create and initialize any instance member variables
when you use the new expression to create an object of a class. To initialize a static class,
or static variables in a non-static class, you must define a static constructor. For more
information, see Static Constructors (C# Programming Guide).
class CoOrds
{
public int x, y;
// constructor
public CoOrds()
{
x = 0;
y = 0;
}
}
Note:
For clarity, this class contains public fields. The use of public fields is not a recommended
programming practice because it allows any method anywhere in a program unrestricted
and unverified access to an object's inner workings. Data members should generally be
private, and should be accessed only through class methods and properties.
This instance constructor is called whenever an object based on the CoOrds class is
created. A constructor like this one, which takes no arguments, is called a default
constructor. However, it is often useful to provide additional constructors. For example,
we can add a constructor to the CoOrds class that allows us to specify the initial values for
the data members:
This allows CoOrd objects to be created with default or specific initial values, like this:
Instance constructors can also be used to call the instance constructors of base classes.
The class constructor can invoke the constructor of the base class through the initializer,
as follows:
In this example, the Circle class passes values representing radius and height to the
constructor provided by Shape from which Circle is derived. A complete example using
Shape and Circle appears in this topic as Example 3.
Example 1
The following example demonstrates a class with two class constructors, one without
arguments and one with two arguments.
class CoOrds
{
public int x, y;
// Default constructor:
public CoOrds()
{
x = 0;
y = 0;
}
class MainClass
{
static void Main()
{
CoOrds p1 = new CoOrds();
CoOrds p2 = new CoOrds(5, 3);
Example 2
In this example, the class Person does not have any constructors, in which case, a default
constructor is automatically provided and the fields are initialized to their default values.
class TestPerson
{
static void Main()
{
Person person = new Person();
Notice that the default value of age is 0 and the default value of name is null. For more
information on default values, see Default Values Table (C# Reference).
Example 3
The following example demonstrates using the base class initializer. The Circle class is
derived from the general class Shape, and the Cylinder class is derived from the Circle
class. The constructor on each derived class is using its base class initializer.
class TestShapes
{
static void Main()
{
double radius = 2.5;
double height = 3.0;
Private Constructors
A private constructor is a special instance constructor. It is generally used in classes that
contain static members only. If a class has one or more private constructors and no public
constructors, other classes (except nested classes) cannot create instances of this class.
For example:
class NLog
{
// Private Constructor:
private NLog() { }
The declaration of the empty constructor prevents the automatic generation of a default
constructor. Note that if you do not use an access modifier with the constructor it will still
be private by default. However, the private modifier is usually used explicitly to make it
clear that the class cannot be instantiated.
Private constructors are used to prevent creating instances of a class when there are no
instance fields or methods, such as the Math class, or when a method is called to obtain
an instance of a class. If all the methods in the class are static, consider making the
complete class static. For more information see Static Classes and Static Class Members
(C# Programming Guide).
Example
The following is an example of a class using a private constructor.
class TestCounter
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter(); // Error
Counter.currentCount = 100;
Counter.IncrementCount();
Console.WriteLine("New count: {0}", Counter.currentCount);
Notice that if you uncomment the following statement from the example, it will generate
an error because the constructor is inaccessible because of its protection level:
Static Constructors
A static constructor is used to initialize any static data, or to perform a particular action
that needs performed once only. It is called automatically before the first instance is
created or any static members are referenced.
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline;
A static constructor is called automatically to initialize the class before the first instance is
created or any static members are referenced.
The user has no control on when the static constructor is executed in the program.
A typical use of static constructors is when the class is using a log file and the constructor
is used to write entries to this file.
Static constructors are also useful when creating wrapper classes for unmanaged code,
when the constructor can call the LoadLibrary method.
If a static constructor throws an exception, the runtime will not invoke it a second time,
and the type will remain uninitialized for the lifetime of the application domain in which
your program is running.
Example
In this example, the class Bus has a static constructor and one static member, Drive().
When Drive() is called, the static constructor is invoked to initialize the class.
// Instance constructor
public Bus(int routeNum)
{
RouteNumber = routeNum;
Console.WriteLine("{0} is created.", RouteNumber);
}
// Instance method.
public void Drive()
{
TimeSpan elapsedTime = DateTime.Now - globalStartTime;
class TestBus
{
static void Main()
{
Using Constructors
Constructors are class methods that are executed when an object of a given type is
created. Constructors have the same name as the class, and usually initialize the data
members of the new object.
In the following example, a class named Taxi is defined by using a simple constructor.
This class is then instantiated with the new operator. The Taxi constructor is invoked by
the new operator immediately after memory is allocated for the new object.
class TestTaxi
{
static void Main()
{
Taxi t = new Taxi();
Console.WriteLine(t.isInitialized);
}
}
A constructor that takes no parameters is called a default constructor. Default
constructors are invoked whenever an object is instantiated by using the new operator
and no arguments are provided to new. For more information, see Instance Constructors
(C# Programming Guide).
Unless the class is static, classes without constructors are given a public default
constructor by the C# compiler in order to enable class instantiation. For more
information, see Static Classes and Static Class Members (C# Programming Guide).
You can prevent a class from being instantiated by making the constructor private, as
follows:
class NLog
{
// Private Constructor:
private NLog() { }
Constructors for struct types resemble class constructors, but structs cannot contain an
explicit default constructor because one is provided automatically by the compiler. This
constructor initializes each field in the struct to the default values. For more information,
see Default Values Table (C# Reference). However, this default constructor is only
invoked if the struct is instantiated with new. For example, this code uses the default
constructor for Int32, so that you are assured that the integer is initialized:
int i;
Console.WriteLine(i);
Alternatively, objects based on structs (including all built-in numeric types) can be
initialized or assigned and then used as in the following example:
A constructor can use the base keyword to call the constructor of a base class. For
example:
In this example, the constructor for the base class is called before the block for the
constructor is executed. The base keyword can be used with or without parameters. Any
parameters to the constructor can be used as parameters to base, or as part of an
expression. For more information, see base (C# Reference).
In a derived class, if a base-class constructor is not called explicitly by using the base
keyword, the default constructor, if there is one, is called implicitly. This means that the
following constructor declarations are effectively the same:
public Manager(int initialdata)
{
//Add further instructions here.
}
If a base class does not offer a default constructor, the derived class must make an
explicit call to a base constructor by using base.
A constructor can invoke another constructor in the same object by using the this
keyword. Like base, this can be used with or without parameters, and any parameters in
the constructor are available as parameters to this, or as part of an expression. For
example, the second constructor in the previous example can be rewritten using this:
The use of the this keyword in the previous example causes this constructor to be called:
A constructor can be declared static by using the static keyword. Static constructors are
called automatically, immediately before any static fields are accessed, and are generally
used to initialize static class members
Copy Constructors
Copying a class
C# does not provide a copy constructor. If you create a new object and want to copy the
values from an existing object, you have to write the appropriate method yourself. For
example:
class Car
{
private string plate;
private int mileage;
// Copy constructor.
public Car(Car previousCar)
{
plate = previousCar.plate;
mileage = previousCar.mileage;
}
// Instance constructor.
public Car(string plate, int mileage)
{
this.plate = plate;
this.mileage = mileage;
}
// Get accessor.
public string Details
{
get
{
return "The car : " + plate + " has done "
+ mileage.ToString() + " miles";
}
}
}
class TestCar
{
static void Main()
{
// Create a new car object.
Car car1 = new Car("BB06 YUK", 40000);
Unlike some languages, C# does not provide a copy constructor. If you create a new
object and want to copy the values from an existing object, you have to write the
appropriate method yourself.
Example
In this example, the Person class contains a constructor that takes as the argument
another object of type Person. The contents of the fields in this object are then assigned
to the fields in the new object.
class Person
{
private string name;
private int age;
// Copy constructor.
public Person(Person previousPerson)
{
name = previousPerson.name;
age = previousPerson.age;
}
// Instance constructor.
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
// Get accessor.
public string Details
{
get
{
return name + " is " + age.ToString();
}
}
}
class TestPerson
{
static void Main()
{
// Create a new person object.
Person person1 = new Person("George", 40);
Declaring Classes
A class is an abstract representation for some particular type of object. It can be
described as a template or blueprint for an object, as opposed to the actual object itself.
Thus, objects are an instance of a class - they come into existence at some specific time,
persist for some duration, and then disappear when they are no longer needed. Classes
are the abstract descriptions used by the system to create objects when called upon to do
so.
Declaration
[attributes] [modifiers] class identifier [:base-type]
{
body [;]
}The attributes is optional and is used to hold additional declarative information.
The modifier is optional. The allowed modifiers are static, sealed, abstract, unsafe, public
and internal. If no modifier is supplied then a default of internal is used.
The keyword class must be followed by an identifier that names the class.
base-type may also specify the interfaces implemented by this class. The interfaces must
be listed after the base class name (if specified) and must be separated by commas.
Modifiers
abstract - the class is created solely for the purpose of inheritance. You cannot create an
instance of an abstract class.
unsafe - allows for unsafe constructs such as pointers. Requires the unsafe compiler
option.
public - any item in the current assembly or any assembly that references it, can access
this class.
internal - Any item in the current assembly can access this class.
The access levels protected and private are only allowed on nested classes.
The abstract keyword enables you to create classes and class members that are
incomplete and must be implemented in a derived class.
The sealed keyword enables you to prevent the inheritance of a class or certain class
members that were previously marked virtual.
public class F : E
{
public override void DoWork(int i)
{
// New implementation.
}
}
If a virtual method is declared abstract, it is still virtual to any class inheriting from the
abstract class. A class inheriting an abstract method cannot access the original
implementation of the method—in the previous example, DoWork on class F cannot call
DoWork on class D. In this way, an abstract class can force derived classes to provide new
method implementations for virtual methods.
A sealed class cannot be used as a base class. For this reason, it cannot also be an
abstract class. Sealed classes prevent derivation. Because they can never be used as a
base class, some run-time optimizations can make calling sealed class members slightly
faster.
A class member, method, field, property, or event, on a derived class that is overriding a
virtual member of the base class can declare that member as sealed. This negates the
virtual aspect of the member for any further derived class. This is accomplished by putting
the sealed keyword before the override keyword in the class member declaration. For
example:
public class D : C
{
public sealed override void DoWork() { }
}
internal
The internal keyword is an access modifier for types and type members. Internal types or
members are accessible only within files in the same assembly, as in this example:
For more information about assemblies, see Assemblies and the Global Assembly Cache
(C# Programming Guide).
It is an error to reference a type or a member with internal access outside the assembly
within which it was defined.
Note:
An internal virtual method can be overridden in some languages, such as textual Microsoft
intermediate language (MSIL) using Ilasm.exe, even though it cannot be overridden by
using C#.
Example
This example contains two files, Assembly1.cs and Assembly1_a.cs. The first file contains
an internal base class, BaseClass. In the second file, an attempt to instantiate BaseClass
will produce an error.
// Assembly1.cs
// Compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
// Assembly1_a.cs
// Compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}
In this example, use the same files you used in example 1, and change the accessibility
level of BaseClass to public. Also change the accessibility level of the member IntM to
internal. In this case, you can instantiate the class, but you cannot access the internal
member.
// Assembly2.cs
// Compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}
// Assembly2_a.cs
// Compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}
public
The public keyword is an access modifier for types and type members. Public access is the
most permissive access level. There are no restrictions on accessing public members, as in
this example:
class SampleClass
{
public int x; // No access restrictions.
}
See Access Modifiers (C# Programming Guide) and Accessibility Levels (C# Reference) for
more information.
Example
In the following example, two classes are declared, Point and MainClass. The public
members x and y of Point are accessed directly from MainClass.
class PointTest
{
public int x;
public int y;
}
class MainClass4
{
static void Main()
{
PointTest p = new PointTest();
// Direct access to public members:
p.x = 10;
p.y = 15;
Console.WriteLine("x = {0}, y = {1}", p.x, p.y);
}
}
// Output: x = 10, y = 15
If you change the public access level to private or protected, you will get the error
message:
unsafe
The unsafe keyword denotes an unsafe context, which is required for any operation
involving pointers. For more information, see Unsafe Code and Pointers (C# Programming
Guide).
You can use the unsafe modifier in the declaration of a type or a member. The entire
textual extent of the type or member is therefore considered an unsafe context. For
example, the following is a method declared with the unsafe modifier:
unsafe static void FastCopy ( byte* ps, byte* pd, int count ) {...}
You can also use an unsafe block to enable the use of an unsafe code inside this block. For
example:
unsafe
{
// Unsafe context: can use pointers here.
}
To compile unsafe code, you must specify the /unsafe compiler option. Unsafe code is not
verifiable by the common language runtime.
Example
// compile with: /unsafe
class UnsafeTest
{
// Unsafe method: takes pointer to int:
unsafe static void SquarePtrParam(int* p)
{
*p *= *p;
}
Note:
In the common language runtime (CLR), unsafe code is referred to as unverifiable code.
Unsafe code in C# is not necessarily dangerous; it is just code whose safety cannot be
verified by the CLR. The CLR will therefore only execute unsafe code if it is in a fully
trusted assembly. If you use unsafe code, it is your responsibility to ensure that your code
does not introduce security risks or pointer errors. For more information, see Security (C#
Programming Guide).
In some cases, unsafe code may increase an application's performance by removing array
bounds checks.
Unsafe code is required when you call native functions that require pointers.
In order for C# to compile unsafe code, the application must be compiled with /unsafe.
Delegate
Summary
A delegate is basically a reference to a method. A delegate can be passed like any other
variable. This allows the method to be called anonymously, without calling the method
directly.
For example:
A object can create a delegate that refers to one of its private methods. Then the object
can pass that delegate to another object. The second object could then call that private
method without knowing anything about it (loose-binding).
Code Examples
These examples demonstrate delegates that are not used for events
Example Names:
// Delegate Declaration
public delegate void AcceptCallback();
// Delegate Instance
AcceptCallback doAccept;
Declare a void delegate that takes no parameters:
// Explaination:
// Inside the Sort method, the delegate will be called
// which calls the private Compare method to which it refers
// In this way the Sort method is able to call a method without
// knowing anything about the actual method
}
}
DictionaryBase classes
DictionaryBase Class
Provides the abstract base class for a strongly typed collection of key/value pairs.
Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
Syntax
Visual Basic (Declaration)
<SerializableAttribute> _
<ComVisibleAttribute(True)> _
Public MustInherit Class DictionaryBase _
Implements IDictionary, ICollection, IEnumerable
Visual Basic (Usage)
Dim instance As DictionaryBase
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class DictionaryBase : IDictionary,
ICollection, IEnumerable
Remarks
The foreach statement of the C# language (for each in Visual Basic) requires the type of
each element in the collection. Since each element of the DictionaryBase is a key/value
pair, the element type is not the type of the key or the type of the value. Instead, the
element type is DictionaryEntry. For example:
C#
foreach (DictionaryEntry de in myDictionary) {...}
vb#c#
The foreach statement is a wrapper around the enumerator, which only allows reading
from, not writing to, the collection.
Note:
Because keys can be inherited and their behavior changed, their absolute uniqueness
cannot be guaranteed by comparisons using the Equals method.
Notes to Implementers:
This base class is provided to make it easier for implementers to create a strongly typed
custom collection. Implementers are encouraged to extend this base class instead of
creating their own.
Members of this base class are protected and are intended to be used through a derived
class only.
Examples
The following code example implements the DictionaryBase class and uses that
implementation to create a dictionary of String keys and values that have a Length of 5
characters or less.
Visual Basic Copy Code
Imports System
Imports System.Collections
' Display the contents of the collection using For Each. This is the preferred method.
Console.WriteLine("Contents of the collection (using For Each):")
PrintKeysAndValues1(mySSC)
' Display the contents of the collection using the Keys property and the Item property.
Console.WriteLine("Initial contents of the collection (using Keys and Item):")
PrintKeysAndValues3(mySSC)
Console.WriteLine()
' Uses the For Each statement which hides the complexity of the enumerator.
' NOTE: The For Each statement is the preferred way of enumerating the contents of a
collection.
Public Shared Sub PrintKeysAndValues1(myCol As ShortStringDictionary)
Dim myDE As DictionaryEntry
For Each myDE In myCol
Console.WriteLine(" {0,-5} : {1}", myDE.Key, myDE.Value)
Next myDE
Console.WriteLine()
End Sub 'PrintKeysAndValues1
C#
using System;
using System.Collections;
if ( value.GetType() != typeof(System.String) )
throw new ArgumentException( "value must be of type String.", "value" );
else {
String strValue = (String) value;
if ( strValue.Length > 5 )
throw new ArgumentException( "value must be no more than 5 characters in
length.", "value" );
}
}
protected override void OnSet( Object key, Object oldValue, Object newValue ) {
if ( key.GetType() != typeof(System.String) )
throw new ArgumentException( "key must be of type String.", "key" );
else {
String strKey = (String) key;
if ( strKey.Length > 5 )
throw new ArgumentException( "key must be no more than 5 characters in
length.", "key" );
}
if ( newValue.GetType() != typeof(System.String) )
throw new ArgumentException( "newValue must be of type String.", "newValue" );
else {
String strValue = (String) newValue;
if ( strValue.Length > 5 )
throw new ArgumentException( "newValue must be no more than 5 characters in
length.", "newValue" );
}
}
if ( value.GetType() != typeof(System.String) )
throw new ArgumentException( "value must be of type String.", "value" );
else {
String strValue = (String) value;
if ( strValue.Length > 5 )
throw new ArgumentException( "value must be no more than 5 characters in
length.", "value" );
}
}
// Display the contents of the collection using foreach. This is the preferred method.
Console.WriteLine( "Contents of the collection (using foreach):" );
PrintKeysAndValues1( mySSC );
// Display the contents of the collection using the Keys property and the Item
property.
Console.WriteLine( "Initial contents of the collection (using Keys and Item):" );
PrintKeysAndValues3( mySSC );
Console.WriteLine();
// Uses the foreach statement which hides the complexity of the enumerator.
// NOTE: The foreach statement is the preferred way of enumerating the contents of a
collection.
public static void PrintKeysAndValues1( ShortStringDictionary myCol ) {
foreach ( DictionaryEntry myDE in myCol )
Console.WriteLine( " {0,-5} : {1}", myDE.Key, myDE.Value );
Console.WriteLine();
}
/*
This code produces the following output.
*/