Versions

C# 1.0 - Jan 2002 - .Net Framework 1.0
C# 1.2 - Apr 2003 - .Net Framework 1.1
C# 2.0 - Nov 2005 - .Net Framework 2.0
C# 3.0 - Nov 2007 - .Net Framework 2.0, 3.0, 3.5
C# 4.0 - Apr 2010 - .Net Framework 4.0
C# 5.0 - Aug 2012 - .Net Framework 4.5
C# 6.0 - Jul 2015 - .Net Framework 4.6

Objects

Everything in C# is derived from the Object class.

ValueType is derived from Object.
All value types are derived from ValueType. These types are treated as true value types from other languages (for example, memory is allocated to the stack).
You cannot explicitly derive from ValueType. All structs are derived from ValueType.
Ex: Int32 is a struct derived from ValueType.
Braces

Roman


class MyClass
{
}

Egyptian


class MyClass {
}
Namespaces

Namespaces have a nested structure. Each segment of a namespace like "System.Collections.Generic" is a namespace:
- System
- Collections within System
- Generic within Collections

Nested namespaces may be declared two ways:

namespace System.Collections { }
//or
namespace System 
{
    namespace Collections { }
}

The fully qualified name of a type includes the full namespaces it is within:
- System.Collections.Generic.List<T>

Fully qualified names must be unique within a program.

You cannot declare a namespace within a class, interface, or struct.

Naming Convention

The conventional organization of a project is for the namespaces to correspond to the file structure.
- Files at the root of the project are in namespace "MyProject".
- Files in folder root/Contracts are in namespace "MySpace.Contracts".
- And so on.

Including Libraries

(Rules determined by experimentation)

Library-A: the .Net library you are making.
Library-B: a third-party library you are using within Library-A.

When making Library-A, you can make use of Library-B internally in your project without making it necessary for users of Library-A to also add a reference to Library-B in their project.

When will users of Library-A need to add a reference to Library-B?
- When calling a Library-A method with Library-B Type arguments.
- When calling a Library-A method that returns a Library-B Type, whether or not they capture the return value.
- When referencing a Library-B Type property or field in a Library-A Type object.

Therefore, third-party dependency considerations should not affect how you divide your namespaces. Merely including the namespace in your project does not incur additional references.

Additionally, Visual Studio IntelliSense will report exactly which library you are missing when you try to use a Library-B type.

When referencing Library-B, they will need to reference the same version that Library-A uses.
Naming Conventions

Case

All names are in CamelCase.

Constants and Readonlys have names in all capitals with snake case, such as MAX_COUNT.

Property names start with a capital letter.
Public field names start with a capital letter.
Private field names start with a lower case letter.

Method names start with a capital letter.

Name

Classes have singular names, such as "Customer" instead of "Customers".

Interface names start with "I", such as "IEnumerable".

Fields that are private even within the object start with an underscore, such as _extraPrivateField.
- This indicates that even within the object, this field should not be touched lightly.
- It may indicate a readonly field.

Boolean properties and fields start with "Is" or "Has", such as "IsActive" or "HasErrors".
Methods that return booleans are named the same way.

Acronyms

Acronyms are spelled with only their first character capitalized, such as "Xml" or "Tcp".

Verbose Names

It's ok to have long variable/method/class names. For instance, I recommend saying "synchronizationContext" instead of "syncContext" or worse "syncCnt".

The name might be very long, such as "CheckInRemoteCustomerWithoutSynchronizationUsingDurableLayer".
And maybe some of that information can be refactored into parameter types or the class name.
But if it can't, you need it to be in the field or method name.
Don't leave information out just because the name is long.

Verbose names are easier to read and to understand.
Verbose names are part of self-documenting code.

You only have to write it a few times, but you'll have to read it many many times.
Constructs

Classes

Classes define reference-types.
Classes can contain any type of member.
Classes can define the implementation of any type of member.
Classes that are not abstract nor static can be instantiated.

Interfaces

Interfaces can contain the signatures of methods, properties, events, or indexes.
Interfaces cannot define the implementation of any type of member.
Interfaces cannot be instantiated.

Interfaces cannot contain static members.
Interface members are implicitly public.

When defining Property signatures, an interface can define read and/or write accessibility by including the get and/or set accessor.

Interfaces can be internal. If so, all its members will also be internal.
Interfaces can be declared within a class.

Structs

Structs define value-types.
Structs cannot define explicit parameterless constructors.
Structs cannot define default field values.

(.Net 4.6)

Structs can now define explicit parameterless constructors.

Inheritance

Classes

C# only allows a class to inherit from a single other class.
This avoids ambiguous cases like loops in the inheritance tree, when class D derives from B and C, with B and C both deriving from A.

If class B derives from class A, note that casting a B object to type A does not block usage of the B-specific functionality. It can always be cast back to type B.


class MyClass
{
    private List<string> list = new List<string>();
    
    public IEnumerable<string> MyStrings
    {
        //casting to IEnumerable does not protect your list from editing
        get { return list; }
    }
}

Method Overriding

Overriding instance methods:

class A
{
    public virtual void MyMethod()
    {
    }
}

class B : A
{
    public override void MyMethod()
    {
    }
}

Overriding static methods:

class A
{
    public static void MyMethod()
    {
    }
}

class B : A
{
    public static new void MyMethod()
    {
    }
}

Interfaces

A class can inherit from any number of interfaces, because they are just a list of member signatures.

Interfaces can also inherit from interfaces.

Explicit Interface Implementation:
When a class implements more than one interface with members of the same name, you can explicitly state which member is from which interface.

string IEmployee.Name
{
    get { return _name; }
}
Explicit interface implementations cannot be declared public, and they can only be called when the object is cast to that interface type.
It can differentiate between properties, between methods, or between a property and method with a shared name.

Structs

Structs cannot inherit from classes or structs.

Variance

Assignment Compatibility

Two types are assignment compatible if the right-hand-side belongs to a type that is the same as or is derived from the left-hand-side.

string s = "text";
object o = s;

public class Dog { }
public class Labrador : Dog { }

Labrador l = new Labrador();
Dog d = l;

No data is lost from the right-hand-side object. It maintains its original type.

Covariance

Covariance is a subset of assignment compatibility where the right-hand-side type defines a generic argument that is the same as or is derived from the left-hand-side's generic argument.

List<string> s = new List<string>() { "a", "b", "c" };
List<object> o = s;

object[] o = new string[] { "a", "b", "c" };

Example: the delegate specifies an object return type. You may assign a method to it that returns a string.

static string GetString() {...}
...
Func<object> myDelegate = GetString;

Declaring an interface generic type covariant:
(not valid for parameter types)
(cannot be used to define generic-type constraints)

interface ICovariant<out T>
{
    T GetThing();
    void DoThing(Action<T> callback);
}
This allows the interface method to have more-derived return types that the specified generic type.

Covariance operations may not be type-safe. (You may cause run-time errors)

Contravariance

Contravariance is a reversal of assignment compatibility.
The left-hand-side type defines a generic argument that is the same as or is derived from the right-hand-side's generic argument.

List<object> o = new List<object>() { "a", "b", "c" };
List<string> s = o;

//given method "static void SetObject(object o)"
Action<object> o = SetObject;
Action<string> s = o;

Example: the delegate specifies a string parameter type. You may assign a method to it that accepts an object.

static void SetObject(object o) {...}
...
Action<string> myDelegate = SetObject;

Declaring an interface generic type contravariant:
(not valid for return types)

interface IContravariant<in T>
{
    void SetThing(T t);
    void DoThing<T>() where T : U;
}
This allows the interface method to have more-derived argument types that the specified generic type.

Covariance operations may not be type-safe. (You may cause run-time errors)

Members

Field

a variable declared directly in a class or struct
see Instance Fields vs Static Fields

Property


public int Name
{
    get; //get accessor
    set; //set accessor
}
special methods called accessors provide a flexible mechanism to read and write data

Method

functions specific to a class

To get reflection information:

using System.Reflection;

public class MyType 
{ 
    public void MyMethod() { }
}

//within method...
Type type = typeof(MyType);
MethodInfo methodInfo = type.GetMethods()[0];
    
Event

publisher classes raise events to alert subscriber classes
    
Operator

such as + ++ - * / ?: new

Index

allows a class to be indexed like an array
resembles a Property

public int this[int i]
{
    get;
    set;
}

Indexes can accept a variaty of parameters. You can overload indexors by using different parameter lists in the same object.


public class MyClass<T>
{
    private List<T> list = new List<T>();
    private Dicationary<string, T> dictionary = new Dicationary<string, T>();
    
    public T this[int key]
    {
        get 
        {
            return list[key];
        }
    }
    
    public T this[int row, int column]
    {
        get 
        {
            return list[row][column];
        }
    }
    
    public T this[string key]
    {
        get
        {
            return dictionary[key];
        }
    }
    
    public T this[params string[] keys]
    {
        get
        {
            return //something that uses multiple string keys
        }
    }
}
//calling the indexors
MyClass<Object> myClass = new MyClass<Object>();
Object a = myClass[5];
Object b = myClass["name"];
Object c = myClass["a", "b", "c"];
    
Constructor

special functions called on class instantiation
Constructors do not have a return type

Customer() { }

Constructor chaining to a base-type constructor:

class A
{
    public A(int x) 
    {
        //handle x
    }
}
class B : A
{
    public B(int x, int y) : base(x)
    {
        //handle y
    }
}

Constructor chaining to another constructor in this type:

class A
{
    public A(int x) : this(x, defaultY)
    {
    }
    public A(int x, int y)
    {
        //handle x and y
    }
}

Static Constructor

Special function called only once per type, either automatically before the first instance is created, or automatically before the first static method is called. The static constructor can initialize static fields, or run other one-time operations.

class A
{
    static A(int x)
    {
    }
    public A(int y)
    {
    }
}

Destructor

a special function to destruct a class
only one allowed per class
Destructors cannot be called, they are invoked automatically
the Destructor implicitly calls Finalize on the object's base class
Destructors do not have a return type

~Customer() { }

Nested Type

a class or struct declared inside another class
the inner class can only be used by the outer class

C# 6.0 One-Liners
    
Auto Property Initializers

Succinct read-only property initialization.

As of C# 6.0 (.Net Framework 4.6)


public string Name { get; } = "Steven";

public DateTime Timestamp { get; } = new DateTime();

public int Id { get; } = NextId();

Expression Bodied Methods

Succinct one-line methods.

As of C# 6.0 (.Net Framework 4.6)


Public override string ToString() => string.Format("{0} {1}", X, Y);

Expression Bodied Properties

Succinct one-line read-only properties.

As of C# 6.0 (.Net Framework 4.6)


Public int Area => Width * Height;

Access Modifiers

Access modifiers can be used on members and types (classes, structs, interfaces).

Public

Accessible to the current assembly and any assembly referencing it

Private

Accessible to the same class or struct.
One instance of the class will have access to private members of another instance of the same class.

Protected

Accessible to the same class or struct, and to any class directly derived from this one.

Only accessible to other classes when referrenced through a derived type.

class A 
{ 
    protected int x = 5; 
}

class B : A 
{ 
    public B() 
    { 
        x = 6; //valid
    } 
}

class C
{
    public static void Main()
    {
        A a = new A();
        B b = new B();
        
        a.x = 10; //INVALID
        b.x = 10; //valid
    }
}

Internal

Accessible to the current assembly only

Protected Internal

Accessible to the current assembly, and to any class directly derived from this one in another assembly

Other Modifiers

Abstract Class

A class that cannot be instantiated, it can only be derived from.

Classes are either abstract or concrete. (Concrete classes do have a special keyword, they just lack the abstract keyword.)

Abstract Method

A method signature with no implementation that must be defined in the derived class
Only valid in abstract classes

Sealed Class

Class cannot be inherited from

New

Explicitly hides a member inherited from a base class, when that member was not virtual

Override

Defines a new implementation of an inherited virtual member

Virtual

Marks that a member may be overriden in a derived class

Static Member

A member that belongs to the type instead of to an instance of the type

Static Class

A class that cannot be instantiated, but whose static members can be accessed
All members of the class must also be static
The class is implicitly sealed

Const

immutable values known at compile time
only built-in types (primitives + Objects) can be declared as Constants
constants are implicitly also static
constant values can only be set when they are declared
    
Readonly

A field that can only be set (once) in a Constructor or where the field is declared
This field cannot be set in a derived class

Extern

A method that is implemented externally, such as in another assembly

Partial

Allows the definition of a class, struct, or interface to be spread across several files

Implicit

Declare an implicit user-defined type conversion.

class MyType
{
    private string term;
    private string description;
    
    public static implicit operator string(MyType a)
    {
        return a.ToString();
    }
    
    public override string ToString()
    {
        return term + ": " + description;
    }
}

Explicit

Declare an explicit user-defined type conversion. (You cannot define both an implicit and explicit conversion between the same two types)

class MyType
{
    private string term;
    private string description;
    
    public static explicit operator string(MyType a)
    {
        return a.ToString();
    }
    
    public override string ToString()
    {
        return term + ": " + description;
    }
}


    
Int

Float

32-bit floating point number. Can hold 7 significant digits.

Cannot accurately store all numbers within its precision range.

Double

64-bit floating point number - more precise than float. Can hold 15 to 16 significant digits.

Cannot accurately store all numbers within its precision range.

NaN

NaN: Not a Number


if(Double.IsNaN(x)
{
}

Infinity


if(Double.IsInfinity(x)) //either negative or positive
{
}
if(Double.IsNegativeInfinity(x))
{
}
if(Double.IsPositiveInfinity(x))
{
}

Decimal

128-bit floating point number - more precise than double. Can hold 28 to 29 significant digits. Comes with slower operations.

Decimal can accurately store any number within its precision range.

Strings

Regular String Literals


"string"
"\tstring" //escape character interpreted as Tab

Escape characters:
single quote \'
double quote \"
backslash \\
?? \0 \u \U
octal notation \[0-9]+
hex notation \x[0-9a-fA-F]{1,4}
alarm sound \a
backspace \b
formfeed \f
new line \n
carriage return \r
horizontal tab \t
vertical tab \v

Verbatim String Literals


@"string"
@"\tstring" //the backslash and t are kept as they are
@"quotes""here" //the only escape sequence is two double quotes are interpreted as one

Verbatim string literals can span multiple lines.

String Interning

All string literals in your code are compiled into one distinct list to be referenced at runtime, so creating a string literal within a loop will not result in 1000 strings being created - each iteration will reference the same immutable string.

You can add strings to the interning list at runtime. Use this if you expect to use this custom string frequently:

String.Intern(myCustomString);

String Formatting

for String.Format or Console.WriteLine

Insert text into string based on the index. This is faster than string concatenation when combining four or more strings.

string s = String.Format("{0} is on the {1} under the {2}", noun1, noun2, noun3);

Format numbers

Console.WriteLine("${#,0.00}", amount); //show exactly 2 decimal places, show at least one whole digit, use comma as thousands separator

Format dates

Console.WriteLine("{0:MM-dd-yyyy}", DateTime.Now);

Align text

Console.WriteLine("{0,10}{1,20}{2,-5}", a, b, c); //number after comma gives width of column, negative number means left-align text

Padding

string x = "abc".PadLeft(5); //add spaces to beginning of string until length equals 5

Hexadecimal

int num = 56;
string upperCaseHex = num.ToString("X");
string lowerCaseHex = num.ToString("x");
string upperCaseHex_2Digits = num.ToString("X2");
string lowerCaseHex_2Digits = num.ToString("x2");

upperCaseHex = String.Format("{0:X}", num);
num = Convert.ToInt32(upperCaseHex, 16);

Repeat a character x times

string s = new String('#', x);

Enums

An enum is a distinct type consisting of a set of named constants. They can be declared at the namespace level, or in a class or struct.

Each constant is automatically assigned an integer value, starting from 0 and incrementing by 1.

There is no validation when a value is set. An integer enum will accept any integer value, not just the ones you defined. You have to call Enum.IsDefined to check that explicitly.


public enum Duration { Daily, Weekly, Monthly };

You can change the starting integer:

public enum Duration { Daily=5, Weekly, Monthly };

You can specify all the values:

public enum Duration { Daily=5, Weekly=3, Monthly=223 };

The default datatype is int, but you can also use byte, sbyte, short, ushort, int, uint, long, or ulong.

public enum Duration : byte { Daily, Weekly, Monthly };

Enums are frequently used for flags, when you intend to combine several options:

public enum MessageType { Error=1, Warning=2, Notice=4, Additional=8 };
...
MessageType selectedMessages = MessageType.Warning | MessageType.Notice;
...
private bool IsFlagSet(MessageType flags, MessageType includesValue)
{
    return ((flags & includesValue) == includesValue);
}
Note that the explicit values are powers of 2. This allows you to use bitwise operators to combine and check the flags.

Converting a string to the enum:

public enum Duration { Daily, Weekly, Monthly };
Duration e = (Duration)Enum.Parse(typeof(Duration), "Daily");

Array


int[] x = new int[10];
int[] y = new int[] { 1, 2, 3 };

x64 Platform: array size limited to 2GB

Multidimensional Arrays


int[,] x = new int[5,8]; //5 rows, 8 columns each
int[,,]y = new int[5,8,3]; //5 rows, 8 columns each, depth of 3 each

int[,] x = new int[,] {{1,2,3}, {4,5,6}}; //init a [2,3] array
int z = x[1,2]; //z = 6

To get length of a dimension:

int rowCount = myArray.GetLength(0);
int colCount = myArray.GetLength(1);
int depthCount = myArray.GetLength(2);

List

x64 Platform: generic list size limited to 2GB
Limit can be overridden with <gcAllowVeryLargeObjects enabled="true" />

Lists use a doubling algorithm: if they need more space, the double of their current space will be allocated to them. You can specify how much space they start with when you initialize the list.
Scope

to do

Multiple Scopes

You can create multiple private scopes within one method. One possible use is to ensure that a variable is not used after its purpose is complete.


public void MyMethod()
{
    {
        int a = 5;
    }
    //variable a is not valid here
    
    {
        //variable a is not valid here either
        int b = 7;
    }
}

It is generally recommended to decompose a large method into several smaller methods instead.
Directives

You cannot intersperse directives within Xml comments - you'll either get a "badly formatted Xml" warning or an "Xml comment is not placed on a valid language element" warning.

Using

The using directive imports namespaces into your program. They do not have to be placed at the top of a file, but that is the standard.


using System;
using System.IO;

You can alias a namespace:

using System;
using My = MyNamespace;
...
My.AddInts(5, 7);

(.Net 4.6)

You can now import a specific static class.


//previously
using System;
using MyNamespace;
...
Utility.AddInts(5, 7);

//also previously
using System;
using static MyNamespace.Utility;
...
AddInts(5, 7);

//now
using System;
using MyNamespace.Utility;
...
AddInts(5, 7);

If Endif

A code block is only compiled if the specified symbol is (or is not) defined.

Test symbol:

    #if DEBUG
        //code
    #elif X
        //code
    #else
        //code
    #endif

Define and undefine symbols:

    #define X
    //code
    #undef X
    
WARNING

Warning will generate a level 1 warning with the specified message when you build.


    #WARNING sql stmt altered to allow build, do not deploy as-is

DEFINE

You can define your own preprocessor symbols. These symbols will only exist within the file they are defined in.


    #define TRACE
    #if TRACE
    //do something
    #endif
    #if (TRACE && DEBUG)
    //do something
    #endif

In Visual Studio, you can have symbols defined based on the compile mode.
    Project > Properties > Build > check Define DEBUG Constant

You can undefine symbols:

    #undef TRACE
    
Preprocessor Symbols

"DEBUG" is a preprocessor symbol.
The custom symbols you create with #define are preprocessor symbols.

Preprocessor symbols are either defined, or undefined. They are not set to a value like a variable.

You can also define symbols in the *.csproj file.

In *.csproj:

  <Project>
    ...
    <PropertyGroup>
      <DefineConstants>$(DefineConstants);MY_SYMBOL</DefineConstants>
    </PropertyGroup>
  </Project>
In code:

    #if MY_SYMBOL
    //do something
    #endif

"DefineConstants" overwrites all current constants.
To add your constant to the current constants, use the "$(DefineConstants);" clause.

You can view your custom defined constants in:
Project properties > Build tab > select a configuration > custom constants are listed at the top

The following are supposed to be built-in preprocessor symbols that are defined based on your target framework, but they aren't working for me.
[Target Framework Symbols]
Framework Moniker Symbol
---------------------------------------------
.NET Framework 2.0 --> net20 --> NET20
.NET Framework 3.0 --> net30
.NET Framework 3.5 --> net35 --> NET35
.NET Framework 4.0 --> net40 --> NET40
.NET Framework 4.5 --> net45 --> NET45
.NET Framework 4.5.1 --> net451 --> NET451
.NET Framework 4.5.2 --> net452 --> NET452
.NET Framework 4.6 --> net46 --> NET46
.NET Framework 4.6.1 --> net461 --> NET461
.NET Framework 4.6.2 --> net462 --> NET462
.NET Framework 4.7 --> net47 --> NET47
.NET Framework 4.71 --> --> NET471
.NET Framework 4.72 --> --> NET472

    #if NET40
    using System.Net;
    #else
    using System.Net.Http;
    using System.Threading.Tasks;
    #endif
Operators

Prefix And Postfix Incrementors


int x = 5;
x++; //postfix x = x + 1
++x; //prefix x = x + 1
x--; //postfix x = x - 1
--x; //prefix x = x - 1

A prefix expression will return the new value of x.
A postfix expression will return the previous value of x.


int[] numbers = new int[] { 0,1,2,3,4,5 };
int index = 2;
int a = numbers[index++]; //a = numbers[2]
index = 2;
int b = numbers[++index]; //b = numbers[3]

In a for loop like (int x=0; x<length; x++) it does not make a difference.

Null Coalesce (??)


x = y ?? 0;
//if y is null, 0 is set instead


x = y ?? z ?? 0;
//chain it

Null Conditional (?)

As of C# 6.0 (.Net Framework 4.6)

aka Null Propagator

Offers succinct null checking


return student?.GetGrades();
//if student is null, null is returned
//otherwise, GetGrades() is run


return students?[index];
//if students is null, null is returned
//otherwise, students[index] is returned


MyEvent?.Invoke(this, new EventArgs());
//if event has no listeners, do nothing
//otherwise, invoke the event

Is

Return true if object is of the specified type:

if(myObject is MyType)
{
}

(C# 7) Return true if object is of the specified type, and cast is to the variable:

if(myObject is MyType myVariable)
{
    //use myVariable
}

Yield

"Yield" can be used instead of IEnumerable.

Auto-return each element in the collection one at a time:

yield return myCollection;
yield break; //end iteration

Method as iterator:

using System.Collections.Generic;

foreach(int i in Power(2, 8))
{
    Console.WriteLine(i);
}

public static IEnumerable<int> Power(int a, int b)
{
    int result = 1;
    for(int i = 0; i < b; i++)
    {
        result = result * a;
        yield return result;
    }
}

Property as iterator:

using System.Collections.Generic;

MyClass myClass = new MyClass();
foreach(int x in myClass.Numbers)
{
    Console.WriteLine(x);
}

public class MyClass
{
    public IEnumerable<int> Numbers
    {
        get
        {
            yield return 5;
            yield return 78;
            yield return 2;
            yield return 12;
        }
    }
}

Operator Overloading

You can overload any operator.


public static MyClass operator +(MyClass a, MyClass b)
{
    return new MyClass(a.X + b.X);
}

You cannot overload logical and (&&) or logical or (||), but you can overload true, false, bitwise and (&), and bitwise or (|).

Parameters

Params

You can specify one 'params' parameter, and it must be the last parameter in the list. A 'params' parameter is always a Collection<T>. When calling the method, you can include any number of type T arguments.


class MyClass
{
    void TestA(params int[] list) { ... }
    void TestB(int a, string b, params object[] list) { ... }
}
...
myClass.TestA(3, 7, 242, 65);
myClass.TestB(56, "text", "a", new Student(), 34.545);

Method overloading only compares method signatures, and the "params" keyword (and other constraints) are not considered. Therefore, this is not allowed because the methods have the same signature:

public void Add(params MyClass[] elements) //must use array
{
    this.elements.AddRange(elements);
}

public void Add(MyClass[] elements) //not allowed - same method name with same parameter types
{
    this.elements.AddRange(elements);
}

public void Add(List<MyClass> elements) //this is ok!
{
    this.elements.AddRange(elements);
}

Out

'out' can be used to cause a parameter to be passed by reference AND the parameter does not have to be initialized before passing it in. The variable MUST have its value set within the function.


public bool TryParse(string text, out int parsedValue)
{
    //attempt to convert text into an integer
    //if successful, set parsedValue to that integer and return true
    //else, set parsedValue to -1 and return false
}

public void DemoOutKeyword()
{
    int parsedValue;
    if(TryParse("644", out parsedValue))
    {
        Console.WriteLine("Parse successful: {0}", parsedValue);
    }
}

Ref

'ref' can be used to cause a parameter to be passed by reference. The variable must be initialized before passing it in. The variable's value does not have to be changed within the function.


public void ChangeValue(ref int x)
{
    x += 5;
}

public void DemoRefKeyword()
{
    int x = 10;
    Console.WriteLine("Before: {0}", x);
    ChangeValue(ref x);
    Console.WriteLine("After: {0}", x);
}

Overloading

'out' and 'ref' look the same to method overloading resoluation. A method with neither will be seen as different from a method with either.

In this example, the "A" methods are valid, the "B" methods are valid, but the "C" methods will cause a compilation error because they are seen as identical.


void A(int, string);
void A(out int, string);

void B(int, string);
void B(ref int, string);

void C(out int, string);
void C(ref int, string);

Boxing And Unboxing

Boxing is assigning a value type variable to a reference type variable. Ie, wrapping a value type inside a reference type.

Unboxing is assigning a reference type variable to a value type variable. Ie, unwrapping a value type that was inside a reference type.
Generics

Generic Class

Encapsulates operations that are not specific to a particular data type
Commonly used for collections

You can convert a concrete class to a generic class by replacing types with type parameters.

public class MyGeneric<T>
{
    public MyGeneric(T myParam)
    {
    }
}

To inherit from a generic class and specify the type:

public class MyGeneric<T> { }

public class MySpecific : MyGeneric<MyType> { }

Getting the Type of a generic:

using System.Reflection;

public class OneGeneric<T> { }
public class TwoGeneric<T,U> { }

//within method...
Type typeOne = typeof(OneGeneric<>);
Type typeTwo = typeof(TwoGeneric<,>);
TypeInfo typeInfoOne = typeOne.GetTypeInfo();
TypeInfo typeInfoTwo = typeTwo.GetTypeInfo();

Generic Method

A method specifying a generic type


static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

Generic Call

Calling a generic method


MyGeneric<int> myInts = new MyGeneric<int>();
Utilities.Swap<int>(ref x, ref y);

Type Parameter Constraints


class MyGeneric<T> where T:IComparable { }
Requires type T to implement interface IComparable


class MyGeneric<T> where T:BaseClass { }
Requires type T to derive from class BaseClass


class MyGeneric<T,U> where T:class where U:struct { }
Requires type T to be a class and type U to be a struct


class MyGeneric<T> where T:IComparable,new() { }
Requires type T to implement interface IComparable, and to implement a parameterless constructor


class MyGeneric<T,U> where T:U { }
Requires type T to be of the same class as U, or of a derived class of U


public void MyMethod<T,U>(int a, string b) where T:AbstractClass,new() { }
All the same constraints can be applied to a generic method. The constraints go between the parameter list and the method body.

Example: Paired Strongly-Type Generic Derivatives

Example demonstrating using abstract generic classes to create a paired set of derived classes that return strong-typed values.

Here are the base abstract classes. They provide weakly typed data.

    /// <summary>
    /// A wrapper around the <see cref='Node'/> class.
    /// Provides extension operations that affect <see cref='Node'/>.
    /// </summary>
    public abstract class ANodeWrapper
    {
        /// <summary>
        /// Returns the wrapped <see cref='Node'/>.
        /// </summary>
        /// <exception cref='Exception'>Node is already set.</exception>
        public Node Node {
            get {
                return node;
            }
            set {
                if(node != null)
                    throw new Exception("Node is already set.");
                node = value;
            }
        }
        private Node node;

        /// <summary></summary>
        protected ALinkWrapper linkWrapper;

        /// <summary></summary>
        public ANodeWrapper()
        {
        }

        /// <summary></summary>
        public ANodeWrapper(Node node)
        {
            Node = node;
        }
    }

    /// <summary>
    /// A wrapper around the <see cref='Link'/> class.
    /// Provides extension operations that affect <see cref='Link'/>.
    /// </summary>
    public abstract class ALinkWrapper
    {
        /// <summary>
        /// Returns the wrapped <see cref='Link'/>.
        /// </summary>
        /// <exception cref='Exception'>Link is already set.</exception>
        public Link Link {
            get {
                return link;
            }
            set {
                //this is the one weak point - can't do type checking at this level
                if(link != null)
                    throw new Exception("Link is already set.");
                link = value;
            }
        }
        private Link link;

        /// <summary></summary>
        protected List<ANodeWrapper> childNodeWrappers = new List<ANodeWrapper>();

        /// <summary></summary>
        public ALinkWrapper()
        {
        }

        /// <summary></summary>
        public ALinkWrapper(Link link)
        {
            Link = link;
        }

        /// <summary>Add child node to end of list.</summary>
        public virtual void Add(ANodeWrapper childNodeWrapper)
        {
            childNodeWrappers.Add(childNodeWrapper);
        }
    }

Here are the mid-level generic classes, still abstract. They provide strongly-typed data.

    /// <summary>
    /// The purpose of <see cref='ANodeWrapper'/> and <see cref='ANodeWrapper{T}'/> is to provide a paired set of strongly-type subclasses.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class ANodeWrapper<T> : ANodeWrapper where T:ALinkWrapper
    {
        /// <summary></summary>
        public T LinkWrapper {
            get {
                return (T)linkWrapper;
            }
            set {
                if(linkWrapper != null)
                    throw new Exception("LinkWrapper is already set.");
                linkWrapper = value;
            }
        }

        /// <summary></summary>
        public ANodeWrapper()
        {
        }

        /// <summary></summary>
        public ANodeWrapper(Node node) : base(node)
        {
        }
    }

    /// <summary>
    /// The purpose of <see cref='ANodeWrapper'/> and <see cref='ANodeWrapper{T}'/> is to provide a paired set of strongly-type subclasses.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class ALinkWrapper<T> : ALinkWrapper where T:ANodeWrapper
    {
        /// <summary></summary>
        public T[] ChildNodeWrappers {
            get {
                return childNodeWrappers.Cast<T>().ToArray();
            }
        }

        /// <summary></summary>
        public ALinkWrapper()
        {
        }

        /// <summary></summary>
        public ALinkWrapper(Link link) : base(link)
        {
        }

        /// <summary>Add child node to end of list.</summary>
        public override void Add(ANodeWrapper childNodeWrapper)
        {
            if(!(childNodeWrapper is T))
                throw new ArgumentException("ChildNodeWrapper is not of type T:" + typeof(T));
            childNodeWrappers.Add(childNodeWrapper);
        }
    }

Here are the paired concrete classes:

    public class NodeWrapper : ANodeWrapper<LinkWrapper>
    {
        public NodeWrapper()
        {
        }

        public NodeWrapper(Node node) : base(node)
        {
        }
        
        //many more extensions operations would go here
    }

    public class LinkWrapper : ALinkWrapper<NodeWrapper>
    {
        public LinkWrapper()
        {
        }

        public LinkWrapper(Link link) : base(link)
        {
        }
        
        //many more extensions operations would go here
    }

Here's the business logic operating on the base abstract classes, but returning strongly-type concrete data.

    /// <summary>
    /// Returns the tree rooted at <paramref name='startingNode'/> recreated with each element wrapped.
    /// The wrapped elements are still interconnected.
    /// </summary>
    /// <typeparam name="T">Node Wrapper type</typeparam>
    /// <typeparam name="U">Link Wrapper type</typeparam>
    /// <param name="startingNode"></param>
    public static T Wrap<T,U>(Node startingNode) where T : ANodeWrapper,new() where U : ALinkWrapper,new()
    {
        T nodeWrapper = new T();
        nodeWrapper.Node = startingNode;

        if(startingNode.Link != null)
        {
            U linkWrapper = new U();
            linkWrapper.Link = startingNode.Link;
            foreach(Node childNode in startingNode.Link.ChildNodes)
            {
                T childNodeWrapper = Wrap<T,U>(childNode);
                linkWrapper.Add(childNodeWrapper);
            }
        }

        return nodeWrapper;
    }
Extension Methods

Extension methods allow you to "add" methods to existing types without creating a derived type. In actuality, you are creating static methods that take in the specified type as a parameter, but you are able to call these methods as if they were a part of that type.

It is recommended to use them sparingly.

Ex: LINQ query operators which extend IEnumerable


public static class MyExtensions
{
    public static int WordCount(this String s)
    {
        return s.Split(new char[] {' ','.','?'}, 
            StringSplitOptions.RemoveEmptyEntries
        ).Length;
    }
}
...
int count = "Multi word test".WordCount();

The first parameter of an extension method specifies the type it extends, and uses the "this" keyword.

Both the extension method, and the class it is a part of, must be static.

You can organize extension methods into any part of your project.

Because extension methods are not actually a part of their objects, they cannot access private or protected members of that object.

Because extension methods are not actually a part of their objects, they can be called on null values, provided the type of the null is explicit.

Extension methods cannot override class/interface methods, so make sure their signature is unique.

.Net 2.0 does not support extension methods, only .Net 3.0 and higher.

Data Annotations

Located in System.ComponentModel.DataAnnotations.

Attributes that can be added to class properties. You can add multiple types of annotations to a single property.

Validation Attributes


[StringLength(50)] //maximum string length
[Range(0.01,100.00)] //range of valid values
[Required(ErrorMessage="Provide phone number.")]
[RegularExpression(@"....")] //field must conform to a pattern
[Compare("Password")] //compare one field to another
[EnumDataType(typeof(MyEnum))] //verifies that value is specified in the enum

The ErrorMessage property is available on all these attributes.

Display Attributes


[Display(...)] //lots of optional properties
[DisplayName("Author")]
[DataType(DataType.EmailAddress)] //tells how to format a string
[Name(...)]
[ShortName(...)]
[Description(...)] //usually for a tooltip
[Prompt(...)] //usually a watermark in an input field
[GroupName(...)] //used to group fields
[Order(...)]
[AutoGenerateField(...)]
[AutoGenerateFilter(...)]
[DisplayColumn(...)] //apply to parent in foreign key relationship
[SortColumn(...)]
[DisplayFormat(DataFormatString="{0:C}")]
[DisplayFormat(ConvertEmptyStringToNull=true, NullDisplayText="Not Specified")]

Custom Attributes

Make a class inheriting from ValidationAttribute and override IsValid. Optionally add new constructors to take in extra parameters.


//defining the attribute
public class MinStringLengthAttribute : ValidAttribute
{
    public int Min { get; set; }
    public override bool IsValid(object obj)
    {
        return (((string)obj).Length >= Min);
    }    
}
//using the attribute
[MinStringLength(Min=5)]

Or use CustomValidationAttribute

//defining the attribute
public class MyClass
{
    public static ValidationResult MyValidationMethod(object obj)
    {
        bool success = //code
        if(success)
            return ValidationResult.Success;
        return new ValidationResult("error message");
    }
}
//using the attribute
[CustomValidation(typeof(MyClass), "MyValidationMethod")]

Delegates

A delegate type represents references to methods with specific parameter lists and return types.


public delegate void MyDelegateA(string a);

MyDelegateA a = new MyDelegateA(methodA);
a("test");

void methodA(string a)
{
    Console.WriteLine(a);
}

Delegates cannot be overloaded; they are differentiated by their name alone.

Action

An action is a delegate that does not return a value.
You can define an Action type parameter without explicitly defining a delegate for it.


Action<int, string> myAction = new Action<int, string>(Square);
myAction(4, "A"); //"4A"

static void Square(int i, string s)
{
    Console.WriteLine("{0}{1}", i, s);
}

Func

A func is a delegate that returns a value.
The last data type in the definition is the return type.
You can define a Func type parameter without explicitly defining a delegate for it.


Func<int, int> myFunc = new Func<int, int>(Square);
int x = myFunc(4); //16

static int Square(int i)
{
    return i * i;
}

Multicast

You can build up a list of Action delegates, provided they do not use an "out" parameter. When executing the delegate, all methods in the list are executed.


using System;
using System.Text;

delegate void MyFunc(int x);

class Test
{
    public static void Main()
    {
        MyFunc a = new MyFunc(A);
        MyFunc b = new MyFunc(B);
        MyFunc c = a + b; //add to list: a, b
        MyFunc d = c + a; //add to list: a, b, a
        MyFunc e = d - b; //remove from list: a, a
        MyFunc f = d - a; //remove from list: a, b
        c(1);
        d(2);
        e(3);
        f(4);
    }
    
    public static void A(int a)
    {
        Console.WriteLine("A: "+a);
    }
    
    public static void B(int b)
    {
        Console.WriteLine("B: "+b);
    }
}

Event

publisher classes raise events to alert subscriber classes


public delegate void EventHandlerB(object sender, EventArgsB e);

public class Publisher
{
    public event EventHandler EventA; //uses basic EventHandler, EventArgs objects
    
    public event EventHandlerB EventB;
    
    public Publisher() { ... }
    
    private void Something() 
    {
        TriggerEventA();
        TriggerEventB();
    }
    
    private void TriggerEventA()
    {
        if(EventA == null) return;
        EventA(this, new EventArgs());
    }
    
    private void TriggerEventB()
    {
        if(EventB == null) return;
        EventB(this, new EventArgsB());
    }
}

public class Subscriber
{
    public Subscriber(Publisher publisher)
    {
        publisher.EventA += new System.EventHandler(OnEventA);
        publisher.EventB += new Publisher.EventHandlerB(OnEventB);
    }
    
    public void OnEventA(object sender, EventArgs e)
    {
    }
    
    public void OnEventB(object sender, EventArgsB e)
    {
    ]
}

public class EventArgsB : EventArgs { ... }

Passing

Passing event to another control

private void passMouseWheelToParent(object sender, MouseEventArgs e)
{
    Control parent = (sender as Control).Parent;
    System.Reflection.MethodInfo onMouseWheel = parent.GetType().GetMethod("OnMouseWheel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    onMouseWheel.Invoke(parent, new object[] { e });
}

Keys

When you click Enter in a single-line TextBox, you get an error-ding-sound. This will suppress it.

private void textBox_KeyDown(object sender, KeyEventArgs e)
{
    if(e.KeyCode == Keys.Enter)
    {
        e.Handled = true;
        e.SuppressKeyPress = true; //stop the error-ding from sounding
    }
}

Naming Conventions

Event delegate:

//subscriber handles the event "EventRaised"
void OnEventRaised(object sender, EventArgs args)
{
}
When there are multiple events with the same "EventRaised" name being handled, I'll use the naming convention "OnObjectEventRaised" to differentiate them.

Custom event arguments:

class SpecificEventArgs : EventArgs
{
    public SpecificEventArgs(/*required data*/)
    {
        //store data locally
    }
}
Usually, EventArgs are immutable objects so that an event subscriber cannot change the value before another event subscriber handles it.

Declare event in class:

//declare type for each specific event handler
public delegate void SpecificEventHandler(object sender, SpecificEventArgs args);
public event SpecificEventHandler NounVerb;

//or
//declare event without requiring a new type for each event handler
public event EventHandler<SpecificEventArgs> NounVerb;
Events are declared as public fields in classes. The compiler automatically adds wrappers to the event field so that it can only be accessed in valid ways - to add/remove subscribers to/from the event.

Invoke the event:

private void MyMethod()
{
    //previously
    if(NounVerb != null) //if there are no subscribers, the event will be null
    {
        NounVerb.Invoke(this, new SpecificEventArgs(/*arguments*/);
    }
    
    //Framework 4.6 and above
    NounVerb?.Invoke(this, new SpecificEventArgs(/*arguments*/);
}
Pass special value "EventArgs.Empty" to indicate that no information is being passed to the event handler.

Microsoft's example does not have a method just for invoking each specific event. So they don't show a naming convention for that pattern.
My suggestion:

private void InvokeNounVerb()
{
    if(NounVerb == null) return;
    NounVerb.Invoke(this, new SpecificEventArgs(/*arguments*/);
}

Event handlers should never have a return value.
To return data, it must be set in the EventArgs. Example: marking an event as cancelled by setting a field in the EventArgs.

You can manage internal events explicitly:

internal event EventHandler<SearchDirectoryArgs> DirectoryChanged
{
    add { directoryChanged += value; }
    remove { directoryChanged -= value; }
}
private EventHandler<SearchDirectoryArgs> directoryChanged;
Attributes

Caller

(.Net 4.5)

Uses reflection to provide runtime information:

using System.Runtime.CompilerServices;

public void MyMethod(normalParam, [CallerMemberName] string name = "", [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string path = "")
{
    Console.WriteLine("This method called by: " + name);
    Console.WriteLine("This method called from line: " + lineNumber);
    Console.WriteLine("This method called from file: " + path);
}
Settings

Application-level settings can only be edited during design, or in the <Application>.exe.config file between application sessions.

User-level settings can be edited and saved during run-time.


Color myColor = Properties.Settings.Default.myColor;
Properties.Settings.Default.myColor = Color.AliceBlue; 
Properties.Settings.Default.Save(); 
Enumerating

When you write

foreach(int x in list) { ... }
It is compiled to

IEnumerator y = list.GetEnumerator();
while(y.MoveNext())
{
    int x = (int)y.Current;
}

IEnumerable

Method signature IEnumerator GetEnumerator();

IEnumerator

Property Current returns the currently selected element.

Method signature bool MoveNext() returns true if there is an element available to get.

Method signature void Reset() starts you back at the beginning of the enumerable.

Confirmed: when the enumerator is first created, or is reset, the pointer is BEFORE the first element in the collection, thus you start by calling MoveNext().


Equality

To enable equality comparisons in a custom object:

/// <duplicate cref="Equals(object)" />
public static bool operator ==(DotNetQualifiedName a, DotNetQualifiedName b)
{
    if(object.ReferenceEquals(a, null) && object.ReferenceEquals(b, null))
        return true;
    if(object.ReferenceEquals(a, null) || object.ReferenceEquals(b, null))
        return false;
    return a.Equals(b);
}

/// <duplicate cref="Equals(object)" />
public static bool operator !=(DotNetQualifiedName a, DotNetQualifiedName b)
{
    if(object.ReferenceEquals(a, null) && object.ReferenceEquals(b, null))
        return false;
    if(object.ReferenceEquals(a, null) || object.ReferenceEquals(b, null))
        return true;
    return !a.Equals(b);
}

/// <summary>Names converted to strings must match exactly to be considered equal.</summary>
public override bool Equals(Object b)
{
    if(!(b is DotNetQualifiedName))
        return false;
    if(object.ReferenceEquals(this, null) && object.ReferenceEquals(b, null))
        return true;
    if(object.ReferenceEquals(this, null) || object.ReferenceEquals(b, null))
        return false;

    DotNetQualifiedName other = (b as DotNetQualifiedName);
    return (this.LocalName == other.LocalName && this.FullNamespace == other.FullNamespace);
}

/// <summary></summary>
public override int GetHashCode()
{
    if(FullNamespace == null) return LocalName.GetHashCode();
    return LocalName.GetHashCode() ^ FullNamespace.GetHashCode();
}

/// <summary>
/// Names are sorted alphabetically, per namespace, starting with the root.
/// </summary>
public int CompareTo(object b)
{
    if(!(b is DotNetQualifiedName))
        return -1;
    if(this.Equals(b))
        return 0;
    if(object.ReferenceEquals(this, null))
        return -1;
    if(object.ReferenceEquals(b, null))
        return 1;

    DotNetQualifiedName other = (b as DotNetQualifiedName);
    int namespaceComparer = this.FullNamespace.CompareTo(other.FullNamespace);
    if(namespaceComparer != 0)
        return namespaceComparer;
    return this.LocalName.CompareTo(other.LocalName);
}

To avoid infinite recursion, use this method of checking for null values:

//use this
if (object.ReferenceEquals(myObject, null))

//instead of this
if(myObject == null)
Comparable

Interface IComparable is required for LINQ comparisons.


public MyClass : IComparable
{
    public int CompareTo(object other)
    {
        if(!(other is MyClass))
            return -1; //return whatever makes the most sense
        if(this < (other as MyClass))
            return -1;
        if(this == (other as MyClass))
            return 0;
        return 1;
    }
}

Configuration

AppSettings

Add an App.Config file to the project. Add settings like this.

<configuration>
    <appSettings>
        <add key="keyA" value="valueA" />
        <add key="keyB" value="valueB" />
    </appSettings>
</configuration>

Access it like so.

using System.Configuration;

public class MyClass
{
    public string KeyA
    {
        get
        {
            return ConfigurationManager.AppSettings["KeyA"];
        }
    }
}

Add Reference

If you need to add a library reference in a config, do this:

<?xml version="1.0"?>
<configuration>
    <system.web> <!--Web.config example-->
        <compilation debug="true" targetFramework="4.5.2">
            <assemblies>
                <add assembly="System.ServiceModel.Activations"/><!--new reference-->
            </assemblies>
        </compilation>
    </system.web>
</configuration>
Regular Expression Object

Regular expressions quickly parse large amounts of text to find specific character patterns. They extract, edit, replace, and delete text substrings.


using System.Text.RegularExpressions;

RegexStringValidator

If you are just validating a string conforms to a pattern, use a RegexStringValidator.


RegexStringValidator validator = new RegexStringValidator(@"^[A-Z]{3}$");
try
{
    validator.Validate(myString);
}
catch(ArgumentException)
{
    //validation failed
}

Validate is a void method, it just throws an exception if the comparison fails.

Specific Substring

If you are looking for a specific substring (rather than a pattern) use the String class methods.


myString.Contains(substring);
myString.StartsWith(substring);
myString.EndsWith(substring);
myString.IndexOf(substring);
myString.LastIndexOf(substring);

Static Vs Instance Methods

All the Regex methods have both a static version and an instance version.

Regex is an immutable object, so when using instance methods, it will compile your search pattern once and let you use it over and over.

If you use the static methods, your search pattern will be compiled and cached. Usually the cache holds up to 15 pattern, so performance is similar for either method, up to a point.

Examples


Regex r = new Regex(@"\b(\w+)\s\1\b", RegexOptions.IgnoreCase);
MatchCollection matches = r.Matches(myString);
foreach(Match match in matches)
{
    Console.WriteLine(match.Value);
}


if(r.IsMatch(myString))
{
    //at least one match was found
}


Match match = r.Match(myString); //returns first match
while(match.Success)
{
    Console.WriteLine("'{0}' found at index {1}", match.Value, match.Index);
    match = match.NextMatch();
}


string[] splits = r.Split(myString); //splits string at beginning of each match


//instance version
string result = r.Replace(myString, replacementString); //replace all matches with replacement

//static version
string result = Regex.Replace(myString, @"\b(\w+)\s\1\b", replacementString);


public MyClass
{
    public static string MyMethod(Match m)
    {
        //return replacement string for this particular match
    }
}
string result = r.Replace(myString, new MatchEvaluator(MyClass.MyMethod));

Regular Expression Patterns

Character Escapes

\a = \u0007 = alarm sound
\b = \u0008 = backspace
\t = \u0009 = tab
\n = \u000A = new line
\v = \u000B = vertical tab
\f = \u000C = form feed
\r = \u000D = carriage return
\e = \u001B = escape key
\nn or \nnn (where each n is a digit) = octal character (ex: \040 = space)
\xnn (where each n is a hex-digit) = hexadecimal character (ex: \x20 = space)
\cX or \cx (where X and x are alphabet characters) = control-character (ex: \cC = Ctrl-C)
\unnnn (where each n is a hex-digit) = unicode character (ex: \u0020 = space)
\x (where x is any character) = use the character as is (ex: \* = asterisk)

Anchors

Anchors are "atomic zero-width assertions", meaning they cause a match to succeed or fail based on the current position in the string, and they do not cause the current position to change.

^ = beginning of string or line
$ = end of string or line
\A = beginning of string
\Z = end of string or line ??
\z = end of string
\G = beginning of string, or end of previous match
\b = boundary between \w and \W (or vice versa)
\B = not \b


Pattern "\Gx\dx"
String "x1xx3xx5xy7yx9x"
Matches "x1x", "x3x", "x5x"

Character Classes

[x] = matches any single character inside braces (case sensitive by default)
[^x] = matches any single character NOT inside braces
[x-y] = matches any single character in the range from x to y (including x and y)
[x^y] = matches x, ^, or y (equivalent to [\^xy])


"[abg-mx]" = "[abghijklmx]"

. = wildcard, matches any single character (except "\n")
\p{name] = matches any single character in the named Unicode category or block
\P{name} = not \p{name}


\p{Lu} or \p{IsCyrillic}

\w = matches any single "word" character = alphabet and digits and underscore
\W = not \w
\s = matches any single whitespace character
\S = not \s
\d = matches any single digit
\D = not \d

Grouping Constructs

Grouping constructs delineate subexpressions and capture substrings.

(subexp) = captures subexp match and assigns it to an ordinal group (starting at 1)


Pattern "(\w)\1"
String "AaBBccdeed"
Matches "BB", "cc", "ee"

(?<name>subexp) = captures subexp match and assigns it to a named group


Pattern "(?<letter>\w)\k<letter>"
String "AaBBccdeed"
Matches "BB", "cc", "ee"

(?<nameA-nameB>subexp = creates a balancing group (see Balancing Group Definition below)

(?:subexp) = does not capture subexp match
(?imnsx-imnsx:subexp) = toggles match options within the subexp (see Miscellaneous Constructs)


"(?i:\w)" //turns ignore case on within the subexp
"(?-i:\w)" //turns ignore case off withint the subexp
"(?i-s:\w)" //turns ignore case on, and single line mode off

(?=subexp) = zero-width positive look ahead assertion, like an Anchor looking for a specific pattern


Pattern "\w+(?=\.)"
String "The dog. Is Happy."
Matches "dog", "Happy" because they have a period after them

(?!subexp) = zer-width negative look ahead assertion, like an Anchor looking for anything but this specific pattern

(?<=subexp) = zero-width positive look behind assertion, like an Anchor looking for a specific pattern


Pattern "(?<=19)\d{2}\b"
String "1851 1999 1950 1905 2003"
Matches "99", "50", "05" because they have a 19 before them

(?<!subexp) = zero-width negative look behind assertion, like an Anchor looking for anything but this specific pattern

(?>subexp) = greedy subexpression, meaning no backtracking

The greedy subexpression is used to speed up large processes. No backtracking means that if (ex) string index 5 through 9 seem to match but index 10 makes the match fail, then checking will continue forward from 10 instead of backtracking to 6.

Quantifiers

* = match previous element 0 or more times
+ = match previous element 1 or more times
? = match previous element 0 or 1 times


"x*" matches "", "x", "xx", "xxx"...
"(xyz)*" matches "", "xyz", "xyzxyz"...

{n} or {n}? = matches previous element exactly n times
{n,} = matches previous element at least n times
{n,m} = matches previous element from n to m times

You can append a ? to end of any quantifier to make it match as few times as possible.

*? = matches previous element 0 or more times AND ALSO as few times as possible
+? = matches previous element 1 or more times AND ALSO as few times as possible
?? = matches previous element 0 or 1 times AND ALSO as few times as possible
{n,}? = matches previous element at least n times AND ALSO as few times as possible
{n,m}? = matches previous element n to m times AND ALSO as few times as possible

Backreference Constructs

\number = matches the value of a numbered subexpression

These groups are numbered left to right, starting at 1, and can go above 9.


Pattern "(aaa)x\1"
String "aaaxaaa"
Matches "aaaxaaa"

\k<name> = matches the value of a named subexpression

These named groups are still given a number, in sequence with the non-named groups.


Pattern "(?<abc>ddd)x\k<abc>x\1"
String "dddxdddxddd"
Matches "dddxdddxddd"

Alternation Constructs

| = matches any 1 element separated by vertical bar


Pattern "th(e|is|at)"
String "the house is this way, not that"
Matches "the", "this", "that"

(?(subexp)yes|no) = the subexp is a zero-width assertion, if assertion is true then match yes otherwise match no


Pattern "(?(Wh)at|one)"
String "What is the tone?"
Matches "What", "one"

(?(name)yes|no) = name is the name or number of a backreference construct, if that construct got a match then match yes otherwise match no


Pattern "(xxx)(?(1)a|b)"
String "bxxxabb"
Matches "b" (the first one), "a"

Substitutions

These are language elements supported in replacement patterns.

$n = (where n is a number) uses substring captured by group n
${name} = uses substring captured by group "name"
$$ = literal $ character
$& = uses whole match
$` = (that is a backtic) uses all of input string up to the match
$' = (that is a quote) uses all of input string after the match
$+ = uses substring captured by last group
$_ = uses entire input string

Options

i = case insensitive
m = multiline mode (^ and $ match start and end of lines, instead of whole input)
n = do not capture unnamed groups
s = single line mode
x = ignore unescaped whitespace in the pattern (use for legibility)


(with x option) "\b(?x) \d+ \s \w+" = "\b(?x)\d+\s\w+"

Miscellaneous Constructs

(?imnsx-imnsx) = toggles the match option for everything to the right


Pattern "A(?i)b\w+"
String "ABC Able aBC"
Matches "ABC", "Able"

(?#comments) = comment your pattern
# = comment starts at unescaped # and goes to end of line

Balancing Group Definition

Matching recursive (nested) structures.

(?<nameA-nameB>subexp)
(?'nameA-nameB'subexp)
(?<-nameB>subexp)

Consider all the matches for nameB to be on a stack. When this match for nameA is found, one match from nameB is popped off the stack. All the text from the last match for nameB to this current match for nameA is pushed onto nameA's stack.

If regex attempts to pop from the nameB stack when the stack is empty, the match fails.

One use is to validate that nested open/close angle braces are valid:

string plainPattern = "^[^<>]*(((?'Open'<)[^<>]*)((?'Close-Open'>)[^<>]*)+)*(?(Open)(?!))$";

//ignore these line breaks, they were added for commenting
string explainedPattern = "
^[^<>]* //allow any number of non-brace characters at beginning
(
    ((?'Open'<)[^<>]*) //"<" pushed onto "Open" stack
    ((?'Close-Open'>)[^<>]*)+ //text pushed onto "Close" stack and one "<" popped from "Open" stack
)*
(?(Open)(?!))$ //success if "Open" stack is empty at the end of the input, because the (?!) is not executed
";

The example above uses (?!). This is a zero-width negative look ahead assertion that will always fail, because it checks for an empty string and you can always find an empty string. Thus this assertion always fails.

Graphics

Create Image


using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

Bitmap bitmap = new Bitmap(width, height);
using(Graphics graphics = Graphics.FromImage(bitmap))
{
    graphics.SmoothingMode = SmoothingMode.AntiAlias;
    graphics.Clear(Color.White);
    //draw on graphics
}
bitmap.Save(saveAsFilename, ImageFormat.Png);

Open Image

To open and edit an image.

using System.Drawing;

public class MyClass
{
    public MyClass()
    {
        Image image = Image.FromFile(fullPath);
        using(Graphics graphics = Graphics.FromImage(image))
        {
            //edit image
        }
        image.Save(fullpath);
    }
}

Strings

Draw text:

using(Graphics graphics = Graphics.FromImage(image))
{
    string text = "Sample Text";
    System.Drawing.Font font = new System.Drawing.Font("Arial", 16);
    System.Drawing.SolidBrush brush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);

    graphics.DrawString(text, font, brush, x, y);
}

Find out how much space the string will take up.

SizeF size = graphics.MeasureString(text, font);

Lines


graphics.DrawLine(pen, startPoint, endPoint);

Arcs

Arcs are bound by Rectangles, start at a degree, and go through a sweep-degree.


//fill in an arc
graphics.FillPie(new SolidBrush(Color.White), rectangle, 0, 360);
//outline an arc
graphics.DrawArc(new Pen(Color.Black, 1), rectangle, 0, 360);

Flip Image

Images use a top-left origin point, like computer screens do.

Flip graphics before drawing on it, so you can calculate using a bottom-left origin.

private void FlipTopToBottom(Graphics graphics, int height)
{
    graphics.ScaleTransform(1, -1);
    graphics.TranslateTransform(0, -height);
}

PDFSharp

Using the PDFSharp library to create PDF documents.

Basic

How to create a new document, draw text on it, and save it:

using System;
using PdfSharp;
using PdfSharp.Drawing; //for XFont
using PdfSharp.Drawing.Layout; //for XTextFormatter
using PdfSharp.Pdf; //for PdfDocument

class Program
{
    static void Main(string[] args)
    {
        PdfDocument document = new PdfDocument();
        PdfPage page = document.AddPage();

        XFont font = new XFont("Verdana", 20, XFontStyle.Bold);
        XGraphics graphics = XGraphics.FromPdfPage(page);
        graphics.DrawString("Testing Text", font, XBrushes.Black, new XRect(0, 0, page.Width, page.Height), XStringFormats.Center);
        
        document.Save("test.pdf"); //creates new or overwrites old
    }
}

Text

XGraphics.DrawString will not line wrap. Use XTextFormatter instead.

PdfPage page = document.AddPage();
XFont font = new XFont("Times New Roman", 12, XFontStyle.Regular);
string text = "The quick brown fox jumped over the lazy dog in the house that Jack built with his two good hands.";
XRect rectangle = new XRect(0, 0, page.Width, page.Height);
using(XGraphics graphics = XGraphics.FromPdfPage(page))
{
    XTextFormatter textFormatter = new XTextFormatter(graphics);
    textFormatter.DrawString(text, font, XBrushes.Black, rectangle, XStringFormats.TopLeft);
}

MeasureString:

using(XGraphics graphics = XGraphics.FromPdfPage(page))
{
    XSize measure = graphics.MeasureString(text, font);
    //measure.Width
    //measure.Height
}
MeasureString ignores leading and trailing spaces.

There is no built in measure for how tall a line-wrapped XTextFormatter string is. Here is a home-rolled solution.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PdfSharp.Drawing;

namespace PdfSharpExtensions
{
    public static class XGraphicsExtension
    {
        public static string[] BreakParagraphIntoLines(this XGraphics graphics, string text, XFont font, double width)
        {
            List<string> lines = new List<string>();
            int startIndex = 0;
            int endIndex = 0;
            int lastSpaceIndex = -1;
            string substring = "";
            while(endIndex < text.Length - 1)
            {
                if(text[endIndex] == ' ')
                {
                    lastSpaceIndex = endIndex;
                }

                substring = text.Substring(startIndex, endIndex - startIndex + 1);
                XSize measure = graphics.MeasureString(substring, font);
                if(measure.Width > width)
                {
                    substring = text.Substring(startIndex, lastSpaceIndex - startIndex + 1);
                    lines.Add(substring);
                    startIndex = lastSpaceIndex + 1;
                    endIndex = startIndex;
                }
                else
                {
                    endIndex++;
                }
            }
            substring = text.Substring(startIndex);
            if(!lines.Contains(substring))
            {
                lines.Add(substring);
            }
            return lines.ToArray();
        }

        public static double MeasureStringHeightWithLineWrap(this XGraphics graphics, string text, XFont font, double width)
        {
            double height = graphics.MeasureString(text, font).Height;
            string[] lines = graphics.BreakParagraphIntoLines(text, font, width);
            return (double)lines.Length * height;
        }
    }
}

Fonts

There are two ways to embed fonts in your pdf.

Specify each font to be embedded:

XPdfFontOptions options = new XPdfFontOptions(PdfFontEmbedding.Always);
XFont font = new XFont("Times New Roman", 12, XFontStyle.Regular, options);

Automatically embed all fonts used on a particular page:

PdfPage page = new PdfPage();
XGraphics graphics = XGraphics.FromPdfPage(page);
graphics.MFEH = PdfFontEmbedding.Automatic;

Units

1 XUnit = 1/72 Inches

Conversions

PdfPage page = document.AddPage();
page.Width = XUnit.FromInch(8.5);
page.Height = XUnit.FromInch(11);
page.Orientation = PageOrientation.Portrait;

Drawing

Colors

XColor paleGray = new XColor { R = 229, G = 229, B = 229 };
XPen outline = new XPen(paleGray);
XBrush fill = new XSolidBrush(paleGray);
graphics.DrawRectangle(new XPen(paleGray), new XSolidBrush(paleGray), XRect);
//or
graphics.DrawRectangle(XPens.LightGray, XBrushes.LightGray, XRect);

Lines

graphics.DrawLine(XPens.Black, x1, y1, x2, y2);
//or
XPen pen = new XPen(XColors.Black, lineThickness);
graphics.DrawLine(pen, x1, y1, x2, y2);

Rectangles

//outline
graphics.DrawRectangle(XPens.Black, x, y, width, height);
graphics.DrawRectangle(XPens.Black, XRect);
//filled
graphics.DrawRectangle(XPens.Black, XBrushes.LightGray, x, y, width, height);
graphics.DrawRectangle(XPens.Black, XBrushes.LightGray, XRect);

Circles

graphics.DrawArc(linePen, x, y, width, height, startDegrees, sweepDegrees);
The circle fits within the bounding rectangle.
0 start = center-right
Positive sweep moves clockwise, negative sweep moves counter-clockwise.

Pie Segments

//outline
graphics.DrawPie(linePen, x, y, width, height, startDegrees, sweepDegrees);
//filled
graphics.DrawPie(XBrushes.Black, x, y, width, height, startDegrees, sweepDegrees);

Images

XImage ximage = XImage.FromFile(fullPathFilename);
graphics.DrawImage(ximage, x, y, ximage.PointWidth, ximage.PointHeight);
CreateSpace recommends using images with at least 200dpi resolution to avoid blurring on PDFs.

Rotating graphics

//put the rotated section in its own using/dispose code block
using(XGraphics graphics = XGraphics.FromPdfPage(page))
{
    graphics.RotateAtTransform(90, new XPoint(page.Width / 2, page.Height / 2));
    graphics.DrawLine(linePen, 0, 0, 300, 300);
}
Or

//save and restore state
XGraphicsState state = graphics.Save();
graphics.RotateAtTransform(90, new XPoint(page.Width / 2, page.Height / 2));
graphics.DrawLine(linePen, 0, 0, 300, 300);
graphics.Restore(state);
Positive degrees rotates the entire graphics section clockwise around the specified point.
If you rotate 90 degrees (clockwise), then a negative Y (moves object left/right) and positive X (moves object up/down) will bring drawings into view.

Working example of vertical text, with the bottom of the text facing the left:

using(XGraphics graphics = XGraphics.FromPdfPage(page))
{
    graphics.RotateAtTransform(90, new XPoint(0, 0));
    XRect rotatedRectangle = new XRect(
        originalRectangle.Y,
        0 - originalRectangle.X - originalRectangle.Width,
        originalRectangle.Height,
        originalRectangle.Width
    );
    graphics.DrawString("Vertical Text", font, XBrushes.Black, rotatedRectangle, XStringFormats.TopLeft);
}

Rotating at the (0,0) point is straight forward. Any other point and the transformation gets weird. See examples:

Visual reference: positive 90 degrees rotation
positive 90 degrees rotation

Visual reference: negative 90 degrees rotation
negative 90 degrees rotation

Graphics

Create

Create and save a PNG

using System;
using System.Drawing;
using System.Drawing.Imaging;

using (Bitmap bitmap = new Bitmap(50, 50)) 
{
    using (Graphics graphics = Graphics.FromImage(bitmap)) 
    {
        graphics.Clear(Color.Green);
    }
    bitmap.Save("green.png", ImageFormat.Png);
}

Settings

Resolution

bitmap.SetResolution(dpiX, dpiY); 

Anti-Aliasing

using System.Drawing.Drawing2D;

graphics.SmoothingMode = SmoothingMode.AntiAlias; //same as SmoothingMode.HighQuality
graphics.SmoothingMode = SmoothingMode.None; //same as SmoothingMode.HighSpeed

Page Unit

graphics.PageUnit = GraphicsUnit.Display; //usually pixels for video and 1/100 inch for printers
graphics.PageUnit = GraphicsUnit.Document; //1/300 inch
graphics.PageUnit = GraphicsUnit.Inch;
graphics.PageUnit = GraphicsUnit.Millimeter;
graphics.PageUnit = GraphicsUnit.Pixel;
graphics.PageUnit = GraphicsUnit.Point; //for printers, 1/72 inch
graphics.PageUnit = GraphicsUnit.World; //world coordinate system unit

Draw

Draw line

graphics.DrawLine(pen, new Point(x1, y1), new Point(x2, y2));
//or
graphics.DrawLine(pen, x1, y1, x2, y2);

Draw rectangle

graphics.DrawRectangle(pen, new Rectangle(originPoint, new Size(width, height)));
//or
graphics.DrawRectangle(pen, originX, originY, width, height);

Draw image file: cover graphics with repeating image

Image pattern = Image.FromFile(patternFilename);
for(int x = 0; x < bitmap.Width + pattern.Width; x += pattern.Width)
{
    for(int y = 0; y < bitmap.Height + pattern.Height; y += pattern.Height)
    {
        graphics.DrawImage(pattern, x, y);
    }
}

Text

Draw vertical text

Font font = new Font("Times New Roman", 14, FontStyle.Regular);
StringFormat format = new StringFormat();
format.FormatFlags = StringFormatFlags.DirectionVertical;
graphics.DrawString("Text", font, Brushes.Black, new Point(0, 0), format);
Text will be drawn rotated 90* clockwise, with the bottom along the X provided.
Images

Bitmap

Basics:

using(Bitmap bitmap = new Bitmap(width, height))
{
    bitmap.SetResolution(resolutionX, resolutionY);
    using(Graphics graphics = Graphics.FromImage(bitmap))
    {
        graphics.SmoothingMode = SmoothingMode.AntiAlias;
        graphics.PageUnit = GraphicsUnit.Pixel;
        //draw on bitmap
    }
    bitmap.Save("filename.png", ImageFormat.Png);
}

C# bitmap runs on GDI Plus, which imposes size limits. The limit seems to be about here:
(maybe)

//works
Bitmap b = new Bitmap(23170,23170);

//doesn't work
Bitmap b = new Bitmap(23171,23170);
IO

Read Text


using System;
using System.IO;

using(StreamReader reader = new StreamReader(filename))
{
    string line = null;
    while((line = reader.ReadLine()) != null)
    {
    }
}

Write Text


using System;
using System.IO;

using(StreamWriter writer = new StreamWriter(filename))
{
    writer.Write("X");
    writer.WriteLine("Y");
}

XmlDocument

To convert XmlDocument or XmlNode contents to a string:

using System.IO;
using System.Xml;

StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
xmlDocument.WriteTo(xmlTextWriter);
string text = stringWriter.ToString();

//Or
StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
xmlNode.WriteTo(xmlTextWriter);
string text = stringWriter.ToString();

Namespace

All elements with be given a default attribute "xmlns=''" unless your specify the namespace. To get an element with no explicit "xmlns" attribute, specify the same namespace as the root element.

using System.Xml;

XmlDocument xmlDocument = new XmlDocument();
XmlNode root = xmlDocument.CreateElement(rootNodeName, namespaceUri);
XmlNode node = xmlDocument.CreateElement(nodeName, root.NamespaceURI);
root.AppendChild(node);
Result:

<rootNodeName xmlns="namespaceUri">
  <nodeName>
  </nodeName>
</rootNodeName>

To add namespace aliases to the root node:

using System.Xml;

XmlDocument xmlDocument = new XmlDocument();
XmlNode root = xmlDocument.CreateElement(rootNodeName, namespaceUri);
XmlAttribute attribute = xmlDocument.CreateAttribute("xmlns:"+alias);
attribute.Value = otherNamespaceUri;
workbookNode.Attributes.Append(attribute);
Result:

<rootNodeName xmlns="namespaceUri" xlmns:alias="otherNamespaceUri">
</rootNodeName>

To specify an aliased namespace for a child node:

using System.Xml;

XmlDocument xmlDocument = new XmlDocument();
XmlNode root = xmlDocument.CreateElement(rootNodeName, namespaceUri);
XmlAttribute attribute = xmlDocument.CreateAttribute("xmlns", alias);
attribute.Value = otherNamespaceUri;
workbookNode.Attributes.Append(attribute);

XmlNode childNode = xmlDocument.CreateElement(alias, childNodeName, otherNamespaceUri);
root.AppendChild(childNode);
Result:

<rootNodeName xmlns="namespaceUri" xlmns:alias="otherNamespaceUri">
  <alias:childNodeName>
  </alias:childNodeName>
</rootNodeName>

To add an attribute under an aliased namespace:

using System.Xml;

XmlDocument xmlDocument = new XmlDocument();
XmlNode root = xmlDocument.CreateElement(rootNodeName, namespaceUri);
XmlAttribute attribute = xmlDocument.CreateAttribute("xmlns", alias);
attribute.Value = otherNamespaceUri;
workbookNode.Attributes.Append(attribute);

XmlNode childNode = xmlDocument.CreateElement(childNodeName, root.NamespaceURI);
XmlAttribute childAttribute = xmlDocument.CreateAttribute(alias, childAttributeName, otherNamespaceUri);
childAttribute.Value = attributeValue;
childNode.Attributes.Append(childAttribute);
root.AppendChild(childNode);
Result:

<rootNodeName xmlns="namespaceUri" xlmns:alias="otherNamespaceUri">
  <childNodeName alias:childAttributeName="attributeValue">
  </childNodeName>
</rootNodeName>


XDocument


using System.Xml.Linq;

XDocument documentA = XDocument.Load(filename);
XDocument documentB = XDocument.Parse("<a><b>text</b></a>");

Loop through direct children:

foreach(XElement element in document.Root.Elements()) //all
{
}
foreach(XElement element in document.Root.Elements(XName)) //all with matching XName
{
}
foreach(XElement element in document.Root.Elements(string)) //all with matching XName.LocalName
{
}
//Elements() method is inherited from XContainer class

Loop through all descendants:

foreach(XElement element in document.Root.Descendants())
{
}

Properties:
XElement.Name = xml tag name
XElement.Value = xml tag inner text

To process XElements that contain plain text mixed with tags:

foreach(XNode node in xElement.Nodes())
{
    //node.NodeType is a System.Xml.XmlNodeType enum value

    //node.NodeType == XmlNodeType.Text for plain text
    //node.ToString() == string value of plain text

    //node.NodeType == XmlNodeType.Element for XElement
    //(node as XElement) casting will work when NodeType is Element
}

To get an attribute value:

string x = xElement.Attribute("attributeName").Value;
//or to protect against null when attribute is not found
string x = xElement.Attribute("attributeName")?.Value;
Excel

EPPlus

Install with NuGet:

install-package EPPlus

Generate excel file:

using OfficeOpenXml;

ExcelPackage newPackage = new ExcelPackage();

ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(name);

worksheet.InsertRow(rowFrom:0, rows:2);
worksheet.Cells["A0"].Value = "Name";
worksheet.Cells["B0"].Value = "Address";
worksheet.Cells["C0"].Value = "Phone";
worksheet.Cells["A1"].Value = "Bob";
worksheet.Cells["B1"].Value = "123 Street";
worksheet.Cells["C1"].Value = "(123) 456-7890";

newPackage.SaveAs(new FileInfo(fullPath));
Database

SQL Server


using System.Data.SqlClient; //in System.Data.dll

Open a connection:

string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=NameDatabase;Integrated Security=True";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();

Read-only query:

string commandString = "select count(*) from dbo.Name";
using(SqlCommand command = new SqlCommand(commandString, connection))
{
    SqlDataReader reader = command.ExecuteReader();
    while(reader.Read()) //get next record
    {
        Console.WriteLine("Found {0} names.", reader.GetValue(0)); //get 0th column from record
    }
}

Update query:

string commandString = "update dbo.NameDetail set IsBoy = @IsBoy, IsGirl = @IsGirl where Id = @Id";
using(SqlCommand command = new SqlCommand(commandString, connection))
{
    SqlParameter isBoyParameter = new SqlParameter("IsBoy", isBoy);
    SqlParameter isGirlParameter = new SqlParameter("IsGirl", isGirl);
    SqlParameter idParameter = new SqlParameter("Id", id);

    command.Parameters.Add(isBoyParameter);
    command.Parameters.Add(isGirlParameter);
    command.Parameters.Add(idParameter);

    command.ExecuteNonQuery();
}

Always close your connection when you're finished with it:

connection.Close();

Exceptions

Recommended Usage

You can throw:
    NotImplementedException
    InvalidOperationException
    NotSupportedException
    PlatformNotSupportedException
    ArgumentException
    ArgumentNullException
    ArgumentOutOfRangeException
    FileNotFoundException
    DirectoryNotFoundException
    DriveNotFoundException
    PathTooLongException
    UriFormatException
    DivideByZeroException
    FormatException
    IndexOutOfRangeException
    KeyNotFoundException
    ObjectDisposedException
    OverflowException
    RankException (array with wrong number of dimensions)
    TimeoutException
    + any of your custom exceptions

Only the system should throw:
    Exception
    SystemException
    ApplicationException
    NullReferenceException
    AccessViolationException
    IndexOutOfRangeException (?? conflicting suggestions from microsoft ??)
    StackOverflowException
    OutOfMemoryException
    ComException
    SEHException
    ExecutionEngineException
    
Exception Filters

(.Net 4.6)

Only catch an exception type if a condition is true. The condition is evaluated in the current scope.


try
{
}
catch(XException ex) if (condition)
{
}
catch(YException ey) if (condition)
{
}
catch(Exception e)
{
}
    
Global Exception Handling

Event System.AppDomain.CurrentDomain.UnhandledException will be triggered when an exception goes unhandled in your application.


using System;

class Program
{
    static void Main(string[] args)
    {
        System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
        throw new Exception("Kaboom");
    }

    static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) 
    {
        Console.WriteLine(e.ExceptionObject.ToString());
        Console.WriteLine("Press Enter to continue");
        Console.ReadLine();
        Environment.Exit(1);
    }
}
Debugging

Debugger Display

The DebuggerDisplay specifies what string to display when the object is inspected in the Debugger Display. The default is object.ToString().

You can place this attribute on a class, property, field, or assembly.


[DebuggerDisplay("Order {Id}")]
class Order
{
    private int Id;
}

The text is shown verbatim, and anything in {} is compiled and run in the scope of the object.

These are valid, but not recommended:

[DebuggerDisplay("{count - 2}")]
[DebuggerDisplay("{count++}")] //this actually edits the object

It is recommended that you call one method that handles the string building:

[DebuggerDisplay("GetHtmlString()")]

Two reasons for this:
1. Complex operations can really slow down your debugger.
2. Contents of the DebuggerDisplay attribute are not compiled until debugger time, and then they are compiled in the current language of the program, which may not be the language your class was written in. This can cause strange errors and behavior.
    
"nq" means no quote, wrapping quotes are removed from the string:

[DebuggerDisplay("Order {Id,nq}")]

Compiler Services

What if you are debugging, and you want to know which method called the method you are looking at. Maybe you are only interested in one caller.

You can add an optional parameter to the method you are looking at:

void MyMethod(int x, int y, ..., string caller = null)
And just update the one caller you are interested in to provide that parameter.

Or, even better, you can use compiler services to automatically provide this data (as of .Net 4.5):

using System.Runtime.CompilerServices;
...
void MyMethod(int x, int y, ..., [CallerMemberName] string caller = null)

CompilerServices includes CallerMemberName, CallerLineNumber, and CallerFilePath.

Event Viewer

Windows:
When an installed program is having problems, open Event Viewer > Windows Logs > Applications and see what errors have been logged.

TDD

Test Driven Development says:
When you are assigned a bug to fix, instead of setting breakpoints and stepping through the code, you can write unit tests to isolate the error. Then you fix it. Then you already have the unit tests.
Unit Testing

General setup

using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class TestClass
{
    [TestMethod]
    public void TestMethod()
    {
        //assign
        //act
        //assert
    }
}

Assert

There are many built-in Assert statements.

Any Assert can be given a last string parameter. This string message will be appended to the default error message if the Assert fails.

Setup

It appears that test cases can be run in any order, regardless of how they are grouped in classes,
so don't rely on all methods in one class being run before the next class.

This initialize method is called once before all the selected test cases in this class are run.
Note: It does not seem to be guaranteed that all tests in one class will be run before tests from other classes - I've gotten other tests running before the cleanup of the previous class ran.

[ClassInitialize]
public static void Initialize(TestContext context)
{
}

This initialize method is called once before each test case in this class is run.

[TestInitialize]
public void Initialize()
{
}

Cleanup

Cleanup does not run if Initialize threw an exception.

This cleanup method is called once after all the selected test cases in this class are run.

[ClassCleanup]
public static void Cleanup()
{
}

This cleanup method is called once after each test case in this class is run.

[TestCleanup]
public void Cleanup()
{
}

Exceptions


[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void TestMethod()
{
    //assign
    //act
    //exception expected instead of assert
}

[TestMethod]
[ExpectedException(typeof(ArgumentException), "Custom description of error.")]
public void TestMethod()
{
    //assign
    //act
    //exception expected instead of assert
}

Private

You can unit test private methods using the PrivateObject.

using Microsoft.VisualStudio.TestTools.UnitTesting;

public class Apple
{
    public Apple()
    {
    }
    
    private int Count()
    {
        return 5;
    }
}

[TestClass]
public class TestClass
{
    [TestMethod]
    public void TestMethod()
    {
        Apple apple = new Apple();
        PrivateObject privateApple = new PrivateObject(apple);
        
        int result = privateApple.Invoke("Count");
        
        Assert.AreEqual(5, result);
    }
}

Internal

You can unit test internal classes by marking the original assembly as friendly to the test assembly.

Add this to either the Properties/AssemblyInfo.cs file or to a code file in the assembly.

using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("NameOfFriendAssembly")]

Marking multiple assemblies as friendly:

using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("NameOfFriendAssemblyA")]
[assembly:InternalsVisibleTo("NameOfFriendAssemblyB")]
//or
[assembly:InternalsVisibleTo("NameOfFriendAssemblyA"), InternalsVisibleTo("NameOfFriendAssemblyB")]

Moq

About

Moq is a popular mocking framework for C#. You can install Moq (and its dependencies) with the NuGet Package Manager.

"Mocking" means creating a derived class of the class you want to test, and overriding its methods to respond the way you want. This is used to setup test scenarios without actually setting up your end-to-end system for each scenario. This allows you to test each part of your system in isolation.

If you find yourself mocking a normal class, you should probably refactor so the class implements an interface and you are mocking the interface. See "Dependency Inversion" for more.

Basic Example


using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

[TestClass]
public class MyClass
{
    [TestMethod]
    public void MyTest()
    {
        Mock<IMyInterface> mock = new Mock<IMyInterface>();
        //setup the mock here
        //run test here, using mock.Object
        //use verify methods on mock, and/or use asserts
        Assert.AreEqual(mock.Object.Property1, "value");
    }
}

Options

Strict Moq will raise an exception for anything invoked in the mock that was not setup first:

Mock<IMyInterface> mock = new Mock<IMyInterface>(MockBehavior.Strict);

Invoke base class implementation if no expectation was setup to override the member.
See "Partial Mocks".
This is required for mocking Web/Html controls in System.Web.

Mock<IMyInterface> mock = new Mock<IMyInterface>() { CallBase = true };

If some member is called that was not setup, automatically create and return a new Mock for that member. This is default recursive Mocks.

Mock<IMyInterface> mock = new Mock<IMyInterface>() { DefaultValue = DefaultValue.Mock };

Setup Methods

Method with parameter and return value:

mock.Setup(i => i.Method("parameter")).Returns("result");

Method that will return each value, in order, as it is called multiple times:

mock.SetupSequence(i => i.Method()).Returns("resultA").Returns("resultB").Returns("resultC").Throws(new InvalidOperationException());

Method with an out parameter and a return value:

int outParameter = 0;
mock.Setup(i => i.Method("parameter", out outParameter)).Returns("result");

Method with a ref parameter:

int refParameter = 0;
mock.Setup(i => i.Method("parameter", ref refParameter));

Throw an exception:

mock.Setup(i => i.Method("parameter")).Throws<InvalidOperationException>();

Accept any parameter of the correct data type:

mock.Setup(i => i.Method(It.IsAny<string>()));

Accept any parameter that is passed by ref: (As of Moq 4.8)

mock.Setup(i => i.Method(ref It.Ref<MyType>.IsAny));

Accept any parameter by type and condition:

mock.Setup(i => i.Method(It.Is<int>(i => i % 2 == 0)));

Accept any parameter by type and range:

mock.Setup(i => i.Method(It.IsInRange<int>(0, 10, Range.Inclusive)));

Accept any parameter by regular expression:

mock.Setup(i => i.MethodCondition5(It.IsRegex("\s+", RegexOptions.IgnoreCase)));

Setup Properties

A property value:

mock.Setup(i => i.Property1).Returns("value");

Mock a hierarchy of objects with one command:

mock.Setup(i => i.Property2.SubProperty3.SubSubProperty4).Returns("value");

Wait for this value to be set during the test:

mock.Setup(i => i.Property3 = "value");

Setup stub: track gets and sets of this property during the test:

mock.SetupProperty(i => i.Property5);
mock.SetupProperty(i => i.Property5, "defaultValue");

Setup all stubs: create stubs for all properties at once:

mock.SetupAllProperties();

Verification

Method was not called:

mock.Verify(i => i.Method("parameter"), Times.Never());

Method was called at least once:

mock.Verify(i => i.Method("parameter"), Times.AtLeastOnce());

Property was got:

mock.VerifyGet(i => i.Property1);

Property was set:

mock.VerifySet(i => i.Property1);

Property was set to specific value:

mock.VerifySet(i => i.Property1 = "value");

Property was set to something in this range:

mock.VerifySet(i => i.Property1 = It.IsInRange(0, 10, Range.Inclusive));

No other invocations were made, except those already verified:

mock.VerifyNoOtherCalls();

Errors

Error: "Mock does not contain a definition for Setup".
Solution: use strongly-typed Mock

//use this
Mock<IMyInterface> mock = new Mock<IMyInterface>();
//instead of this
Mock mock = new Mock<IMyInterface>();
Reflection

Assembly

Load an assembly:

Assembly assembly = Assembly.LoadFrom(assemblyFilename);
This locks the *.dll file. When used through MSBuild, the lock is not released.

Load an assembly without locking the file:

Assembly assembly = Assembly.Load(File.ReadAllBytes(assemblyFilename));
Because of the way this is loaded, any libraries referenced by this one will not be resolvable.
Even if the secondary library is already loaded, it will not be recognized as the referenced library.

Enabling "shadow copying" on the app domain will solve both problems.
This requires creating a whole new app domain because existing ones cannot be edited.

using System;
//...
AppDomainSetup newDomainSetup = new AppDomainSetup();
newDomainSetup.ShadowCopyFiles = "true";

AppDomain newDomain = AppDomain.CreateDomain("", AppDomain.CurrentDomain.Evidence, newDomainSetup);

// Run an executable
newDomain.ExecuteAssembly("path\\program.exe", AppDomain.CurrentDomain.Evidence, commandLineArguments);
//OR run a library method
newDomain.CreateInstance("assemblyName", "typeNameInLibrary");

//...The library type must extend MarshalByRefObject
using System;
using System.Reflection;
public class MyInstance : MarshalByRefObject
{
    public MyInstance()
    {
        //your code here
    }
}
"Shadow copying" means that referenced *.dll files are copied to a temporary directory before being loaded.
This way they are fully loaded without locking the original *.dll file.

Another alternative is to force the current app domain to close when you are done with it. This will release all locked files.
It will only work if it is the last thing done by the application.

public class MyClass
{
    public MyClass()
    {
        Assembly assembly = Assembly.LoadFrom("assemblyFilename");
    }
    
    ~MyClass()
    {
        AppDomain.Unload(AppDomain.CurrentDomain);
    }
}

NameOf

Succinct reflection. Works on classes, methods, properties, and variables.

As of C# 6.0 (.Net Framework 4.6)


public class MyClass
{
    Public double Cost;
}

private string MyMethod(int x)
{
    Return String.Format("{0} {1} {2} {3}", nameof(MyClass), nameof(MyClass.Cost), nameof(MyMethod), nameof(x));
}
//returns “MyClass Cost MyMethod x”

Threads

Requires library System.Threading.dll

Threads will run a specified method. The method must have no parameters and no return type.

Create a new thread:

using System;
using System.Threading;

Thread thread = new Thread(new ThreadStart(MyMethod));
thread.Start();

Thread.Join() will block the current thread until the joined thread completes.
A thread must be started before it can be joined.

To see the id of the current thread:

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
This can be used to verify that an operation is/isn't running in a different thread.

BackgroundWorker

BackgroundWorker is suggested as an easy way to use threading with Windows Forms, so the GUI thread does not freeze.

BackgroundWorker will run an operation on a different thread and then call an event when it is complete.

Note: do not access any GUI objects from these other threads. You'll freeze your GUI.


using System;
using System.ComponentModel;
using System.Threading;

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(MyTask); //set that task to run on this new thread
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnComplete); //trigger event when thread completes

worker.ProgressChanged += new ProgressChangedEventHandler(OnProgressChanged); //optional: report progress to GUI thread
worker.WorkerReportsProgress = true;

worker.WorkerSupportsCancellation = true; //can stop thread partway

worker.RunWorkerAsync(); //start the new thread asynchronously from this one

void OnComplete(object sender, RunWorkerCompletedEventArgs e)
{
    if(e.Error != null)
    {
        //handle exception (you cannot access e.Result or worker.ReportProgress if there is an e.Error)
        return;
    }
    if(e.Canceled)
    {
        //handle cancellation (you cannot access e.Result or worker.ReportProgress if worker is canceled)
        return;
    }
    //on thread completed
    //note that the BackgroundWorker object does not exist by this point
    //you can set a Result object on the DoWorkEventArgs that will flow to here in RunWorkerCompletedEventArgs.Result
}

void OnProgressChanged(object sender, ProgressChangedEventArgs e)
{
    myProgressBar.Value = e.ProgressPercentage;
}

void MyTask(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = (sender as BackgroundWorker);
    for(int i=0; i<100; i++)
    {
        Thread.Sleep(100); //current thread sleeps for 100 milliseconds
        worker.ReportProgress(i); //report progress from 0% to 100% as integer
        if(worker.CancellationPending)
        {
            e.Cancel = true;
            worker.ReportProgress(0);
            return;
        }
    }
    worker.ReportProgress(100);
}

void OnClickCancellationButton(object sender, EventArgs e)
{
    if(worker.IsBusy)
    {
        worker.CancelAsync();
    }
}

Canceling the background worker is not instantaneous. The worker must periodically check for the pending cancellation, which may take time. Here's the recommended design.

BackgroundWorker worker;

void StartTask()
{
    if(worker != null && worker.IsBusy)
    {
        worker.CancelAsync();
        
        while(worker.IsBusy)
        {
            Application.DoEvents(); //this lets the UI thread continue
        }
    }
    
    worker = new BackgroundWorker();
    worker.DoWork += new DoWorkEventHandler(OnDo);
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnCompleted);
    worker.WorkerSupportsCancellation = true;
    worker.RunWorkerAsync();    
}

void OnDo(object sender, DoWorkEventArgs e)
{
    while(doAction)
    {
        if(worker.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
        //work
    }        
}

To pass data into the DoWork method:

worker.RunAsync(dataObject);
//...
private void DoWork(object sender, DoWorkEventArgs e)
{
    MyData data = (e.Argument as MyData);
}

When using worker.ReportProgress, do not run it unless you have a new progress value (int 0 to 100). Every time you call it, (if the GUI thread reacts) it blocks the GUI thread.

Application

To catch all uncaught exceptions that occur in an application:

using System.Threading;
static class MyProgram
{
    [STAThread]
    static void Main()
    {
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        MyForm form = new MyForm();
        Application.Run(form);
    }
}
//....
public class MyForm
{
    public MyForm()
    {
        //this must be set before Application.Run(form)
        Application.ThreadException += new ThreadExceptionEventHandler(OnSystemException);
    }
    private void OnSystemException(object sender, ThreadExceptionEventArgs e)
    {
        //handle e.Exception
    }
}
Confirmed this works on System.TargetInvocationException.
PostSharp

PostSharp is a tool that post-processes your compiled code. The final product is still compiled code.
[How it works]

C# does not currently support anything like the "method as decorator" syntax from Python, which enables you to easily mark a method such that it will run another method before/after itself.

PostSharp, which processes your code after it is compiled, supports this.

To add PostSharp to your solution with NuGet:

install-package PostSharp

PostSharp will run automatically as part of building your solution.

OnMethodBoundaryAspect

Create an aspect class with the custom functionality you want:

[PSerializable]
public class LoggingAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine("The {0} method has been entered.", args.Method.Name);
    }

    public override void OnSuccess(MethodExecutionArgs args)
    {
        Console.WriteLine("The {0} method executed successfully.", args.Method.Name);
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.WriteLine("The {0} method has exited.", args.Method.Name);
    }     

    public override void OnException(MethodExecutionArgs args)
    {
        Console.WriteLine("An exception was thrown in {0}.", args.Method.Name);
    }
}

Add this class as an attribute to any method.

[LoggingAspect]
private void MyMethod()
{
    Console.WriteLine("Hello, world.");
}

Executing this example will print:

The Main method has been entered.
Hello, world.
The Main method executed successfully.
The Main method has exited.

"MethodExecutionArgs.Method" gives you reflection information about the method being decorated.