XML Documentation Comments in C#

In Visual C# you can create documentation for your code by including XML tags in special comment fields in your source code directly before the code block they refer to. For example:

/// 
/// This class performs an important function.
///

public class MyClass{}

When you compile with /doc the compiler will search for all XML tags in your source code and create an XML documentation file.

NoteNote

The XML doc comments are not metadata; they are not included in the compiled assembly and therefore they are not accessible through reflection.

Unsafe Code and Pointers in C#

Unsafe Code and Pointers

To maintain type safety and security, by default C# does not support pointer arithmetic. However, by using the unsafe keyword, it is possible to define an unsafe context in which pointers can be used. For more information about pointers, see the topic Pointer types.

NoteNote

In the common language runtime (CLR), unsafe code is referred to as unverifiable code. Unsafe code in C# is not necessarily dangerous; it is simply code whose safety cannot be verified by the CLR. The CLR will therefore only execute unsafe code if it is within 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 and C#.

Unsafe Code Overview

Unsafe code has the following properties:

  • Methods, types, and code blocks can be defined as unsafe.

  • In some cases, unsafe code may increase an application's performance by removing array bounds checks.

  • Unsafe code is required when calling native functions that require pointers.

  • Using unsafe code introduces security and stability risks.

  • In order for C# to compile unsafe code, the application must be compiled with /unsafe.

Nullable Types in C#

Nullable Types

Nullable types are instances of the System.Nullable struct. A nullable type can represent the normal range of values for its underlying value type, plus an additional null value. For example, a Nullable, pronounced "Nullable of Int32," can be assigned any value from -2147483648 to 2147483647, or it can be assigned the null value. A Nullable can be assigned the values true or false, or null. The ability to assign null to numeric and Boolean types is particularly useful when dealing with databases and other data types containing elements that may not be assigned a value. For example, a Boolean field in a database can store the values true or false, or it may be undefined.
C#
Copy Code

class NullableExample
{
static void Main()
{
int? num = null;
if (num.HasValue == true)
{
System.Console.WriteLine("num = " + num.Value);
}
else
{
System.Console.WriteLine("num = Null");
}

//y is set to zero
int y = num.GetValueOrDefault();

// num.Value throws an InvalidOperationException if num.HasValue is false
try
{
y = num.Value;
}
catch (System.InvalidOperationException e)
{
System.Console.WriteLine(e.Message);
}
}
}

The above will display the output:

num = Null

Nullable object must have a value.
Nullable Types Overview

Nullable types have the following characteristics:

*

Nullable types represent value-type variables that can be assigned the value of null. You cannot create a nullable type based on a reference type. (Reference types already support the null value.)
*

The syntax T? is shorthand for System.Nullable, where T is a value type. The two forms are interchangeable.
*

Assign a value to a nullable type in the same way as for an ordinary value type, for example int? x = 10; or double? d = 4.108;
*

Use the System.Nullable.GetValueOrDefault property to return either the assigned value, or the default value for the underlying type if the value is null, for example int j = x.GetValueOrDefault();
*

Use the HasValue and Value read-only properties to test for null and retrieve the value, for example if(x.HasValue) j = x.Value;
o

The HasValue property returns true if the variable contains a value, or false if it is null.
o

The Value property returns a value if one is assigned, otherwise a System.InvalidOperationException is thrown.
o

The default value for a nullable type variable sets HasValue to false. The Value is undefined.
*

Use the ?? operator to assign a default value that will be applied when a nullable type whose current value is null is assigned to a non-nullable type, for example int? x = null; int y = x ?? -1;

Namespaces in C#

Namespaces

Namespaces are heavily used in C# programming in two ways. First, the .NET Framework uses namespaces to organize its many classes, as follows:

C#

System.Console.WriteLine("Hello World!");

System is a namespace and Console is a class contained within that namespace. The using keyword can be used so that the entire name is not required, like this:

C#

using System;
C#

Console.WriteLine("Hello");
Console.WriteLine("World!");

For more information, see the topic using Directive (C# Reference).

Second, declaring your own namespaces can help you control the scope of class and method names in larger programming projects. Use the namespace keyword to declare a namespace, as in the following example:

C#

namespace SampleNamespace
{
class SampleClass
{
public void SampleMethod()
{
System.Console.WriteLine(
"SampleMethod inside SampleNamespace");
}
}
}

Namespaces Overview

A namespace has the following properties:

  • They organize large code projects.

  • They are delimited with the . operator.

  • The using directive means you do not need to specify the name of the namespace for every class.

  • The global namespace is the "root" namespace: global::system will always refer to the .NET Framework namespace System.

Iterators in C#

Iterators

Iterators are a new feature in C# 2.0. An iterator is a method, get accessor or operator that enables you to support foreach iteration in a class or struct without having to implement the entire IEnumerable interface. Instead, you provide just an iterator, which simply traverses the data structures in your class. When the compiler detects your iterator, it will automatically generate the Current, MoveNext and Dispose methods of the IEnumerable or IEnumerable interface.

Iterators Overview

  • An iterator is a section of code that returns an ordered sequence of values of the same type.

  • An iterator can be used as the body of a method, an operator, or a get accessor.

  • The iterator code uses the yield return statement to return each element in turn. yield break ends the iteration. For more information, see yield.

  • Multiple iterators can be implemented on a class. Each iterator must have a unique name just like any class member, and can be invoked by client code in a foreach statement as follows: foreach(int x in SampleClass.Iterator2){}

  • The return type of an iterator must be IEnumerable, IEnumerator, IEnumerable, or IEnumerator.

The yield keyword is used to specify the value, or values, returned. When the yield return statement is reached, the current location is stored. Execution is restarted from this location the next time the iterator is called.

Iterators are especially useful with collection classes, providing an easy way to iterate non-trivial data structures such as binary trees.

Related Sections

Example

In this example, the class DaysOfTheWeek is a simple collection class that stores the days of the week as strings. After each iteration of a foreach loop, the next string in the collection is returned.

C#

public class DaysOfTheWeek : System.Collections.IEnumerable
{
string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

public System.Collections.IEnumerator GetEnumerator()
{
for (int i = 0; i < m_Days.Length; i++)
{
yield return m_Days[i];
}
}
}

class TestDaysOfTheWeek
{
static void Main()
{
// Create an instance of the collection class
DaysOfTheWeek week = new DaysOfTheWeek();

// Iterate with foreach
foreach (string day in week)
{
System.Console.Write(day + " ");
}
}
}

Output

Sun Mon Tue Wed Thr Fri Sat

Generics in C#

Generics

Generics are a new feature in version 2.0 of the C# language and the common language runtime (CLR). Generics introduce to the .NET Framework the concept of type parameters, which make it possible to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by client code. For example, by using a generic type parameter T you can write a single class that other client code can use without incurring the cost or risk of runtime casts or boxing operations, as shown here:

C#

// Declare the generic class
public class GenericList
{
void Add(T input) { }
}
class TestGenericList
{
private class ExampleClass { }
static void Main()
{
// Declare a list of type int
GenericList<int> list1 = new GenericList<int>();

// Declare a list of type string
GenericList<string> list2 = new GenericList<string>();

// Declare a list of type ExampleClass
GenericList list3 = new GenericList();
}
}

Generics Overview

  • Use generic types to maximize code reuse, type safety, and performance.

  • The most common use of generics is to create collection classes.

  • The .NET Framework class library contains several new generic collection classes in the System.Collections.Generic namespace. These should be used whenever possible in place of classes such as ArrayList in the System.Collections namespace.

  • You can create your own generic interfaces, classes, methods, events and delegates.

  • Generic classes may be constrained to enable access to methods on particular data types.

  • Information on the types used in a generic data type may be obtained at run-time by means of reflection.

Events in C#

Events

Events provide a way for a class or object to notify other classes or objects when something of interest happens. The class that sends (or raises) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.

In a typical C# Windows Forms or Web application, you subscribe to events raised by controls such as buttons and list boxes. You can use the Visual C# integrated development environment (IDE) to browse the events that a control publishes and select the ones that you want to handle. The IDE automatically adds an empty event handler method and the code to subscribe to the event. For more information, see How to: Subscribe to and Unsubscribe from Events (C# Programming Guide).

Events Overview

Events have the following properties:

  • The publisher determines when an event is raised; the subscribers determine what action is taken in response to the event.

  • An event can have multiple subscribers. A subscriber can handle multiple events from multiple publishers.

  • Events that have no subscribers are never called.

  • Events are commonly used to signal user actions such as button clicks or menu selections in graphical user interfaces.

  • When an event has multiple subscribers, the event handlers are invoked synchronously when an event is raised. To invoke events asynchronously, see Calling Synchronous Methods Asynchronously.

  • Events can be used to synchronize threads.

  • In the .NET Framework class library, events are based on the EventHandler delegate and the EventArgs base class.