Here are some personal notes for the C# language and Microsoft's .NET framework.
The primary audience is myself. Those who are are already familiar with a similar language (such as Java or C++), or have seen the C# language before but have since forgotten it may also find this usefull. I will attempt to be as brief as possible with these notes, except in cases where I found the material to be tricky or different from both C++ and Java.
The best C# coding standard that I have found so far can be found on the Microsoft website. The document is called "Design Guidelines for Class Library Developers". The link to this document is HERE.
The CTS is the scheme by which different components written in different languages
can pass data to one another. In it, ALL types are objects, which are ultimately
derived from System.Object. There are two types of objects, Reference
types and ValueTypes. If you need to convert from one type to another (called
"boxing/unboxing"), some unexpected results can happen.
static, readonly
or const.The "primitive" types are called ValueTypes. Although they have some
properties unique to them, they are ultimately still regarded as objects. All
ValueTypes are derived from a special class called System.ValueType,
which is in turn derived from System.Object
All other types not value types are reference types. They ultimately inherit
from System.Object.
Employee e = new Employee(); ContractEmployee c = (Contract Employee)e; // Runtime exception! ContractEmployee c = e as ContractEmployee; // This version works, but c is null! // The keyword "as" returns NULL for bad casts (as in this case) // instead of throwing a bad cast runtime exception!
As far as I know, the concept of attributes is not found in either C++ or java. I am therefore treating them in greater detail in this section. Attributes have the following properties:
Examples of appropriate use of attributes:
There are three types of attributes; Class Attributes, Method Attributes and Field Attributes. Attributes can have parameters and can have their usage defined via other attributes.
As an example, say we wanted to define classes that send messages only to specific remote servers. We can use an attribute here to define if the class we are building is such a class, and if so, which server is it that we are sending info to.
Public enum RemoteServers
{
PENDER,
VALDEZ,
SALTSPRING
}
// Attribute classes are named as "RemoteObjectAttribute"
// But but used as just as "RemoteObject".
// This is a conveniance offered by the compiler
Public class RemoteObjectAttribute : Attribute
{
public RemoteObjectAttribute(RemoteServers Server)
{
this.server = Server
}
protected RemoteServers server;
Public string Server
{
get
{
// note the interesting use of reflection here!
return RemoteServers.GetName(typeof(RemoteServert), this.server);
}
}
}
After the attribute has been defined, we may now use it on a class. To define a class that works only on a remote server now, we may use the attribute as such:
[RemoteObject(RemoteServers.PENDER)]
class MyRemotableClass
{
...
}
To query for an attribute, we need to use reflection. For the different types of attributes, this reflection code is different. For class attributes it is as such:
...
Type type = typeof(MyRemotableClass);
foreach (Attribute attr in type.GetCustomAttributes())
{
RemoteObjectAttribute remoteAttr = attr as RemoteObjectAttribute
if (null != remoteAttr) // Clever! detects if this attribute is a RemoteObject!
{
Console.WriteLine("Create This Object on {0}.", RemoteAttr.Server);
}
}
Methods can be tagged with an attribute instead of whole classes, but the reflection code to query the method attribute is slightly different.
The attribute has no parameters in this example. The attrribute's presence alone will be enough.
public class TransactionableAttribute : Attribute
{
public TransactionableAttribute()
{
}
}
public class TestClass
{
[Transactionable]
public void Foo()
{
}
public void Bar()
{
}
[Transactionable]
public void Baz()
{
}
}
Note the reflection code is different here.
Type type = Type.GetType("TestClass");
foreach (MethodInfo method in type.GetMethods());
{
foreach (attr in method.GetCustomAttributes())
{
if (attr is TransactionableAttribute)
{
Console.WriteLine("{0} is transactionable.", method.Name);
}
}
}
Defining and using field attributes are the same as the method and class cases. Just querying is different.
Type type = Type.GetClass("TestClass);
foreach (FeildInfo field in type.GetFields())
{
foreach(Attribute attr in field.GetCustomAttributes())
{
RegistryKeyAttribute registryKeyAttribute = attr as RegistryKeyAttribute;
if (null != registryKeyAttribute)
{
Console.WriteLine("{0} will be saved in {1}\\\\{2}",
field.Name, RegistryKeyAttribute.Hive, RegistryKeyAttribute.ValueName);
}
}
}
[RegistryKey(RegistryHives.HKEY_CURRENT_USER, "foo")]
Parameters are the things between the brackets.
There are two types of parameters: Positional Parameters and Named Parameters
Valid attribute parameter types: bool, byte, char, double, float, int, short,
string, System.Type, Object, enum, and 1-dimensional arrays.
Positional parameters are defined in the attribute's CONSTRUCTOR. They must
be specified every time an attribute is defined.
example:
[RegistryKey("foo")]
Named parameters are NOT defined in the constructor, but are rather non-static
fields & properties in an attributes definition.
example of using:
[RegistryKey("Foo", Hive = RegistryHives.HKEY_LOCAL_MACHINE)]
Only after all positional parameters are defined can we define the (optional)
named parameters.
example of defining:
public enum RegistryHives
{
HKEY_CLASSES_ROOT = 1; // this is done because "undefined" defaults to zero
HKEY_CURRENT_USER // this way, we can distinguish between initialized and not
}
...
public class RegistryKeyAttribute : Attribute
{
public RegistryKeyAttribute(String ValueName)
{
// This makes a default hive in the constructor to be something meaningfull
if (this.Hive = 0)
this.Hive = RegistryHives.HKEY_CURRENT_USER;
this.ValueName = ValueName;
}
}
An attribute definition can also have it's own class attribute... In the form of an "Attribute Usage" attribute. This tag indicates how and where an attribute is availiable for use. A template for the tag is as follows:
[AttributeUsage(
validon,
AllowMultiple = allowmultiple,
inherited = inherited
)]
This field indicates what classes, fields, methods, etc. that the attribute being defined can be used with. (Ie. can it ONLY be used to define classes, or can we use it with methods too?) The validon parameter is positional, and thus is manditory when defining an attribute. An attribute's default is ALL, however, when no attribute usage attribute is defined. Example of use:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class RemoteObjectAttribute : Attribute
{
...
}
Valid targets are: Assembly, Module, Class, Struct, Enum, Constructor, Method,
Property, Field, Event, Interface, Parameter, Delegate,
All (the default, which is all the above put or'ed together),
Class Members (which is some of the above or'ed together)
Allows / Disallows an attribute to be defined multiple times on the same target.
For example:
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class TransactionableAttribute : Attribute
{...}
...
[Transactionable(1)]
[Transactionable(2)] // This would result in an error
public SomeMethod()
{
}
Determines WHAT you want to annotate.
For example, if we want to annotate the RETURN value rather than a method, we
can do this:
[return: Transactionable]
public long foo()
{
...
}
For the most part, the compiler figures out (via defaults) what is the most
likely thing the programmer wants to do.
Possible identifiers are: assembly, module, type, method, property, event, field,
param, return.
interface IExampleInterface
{
//Example Property Declaration
int testProperty {get;}
//Example Event Declaration
event testEvent Changed;
//Example Indexer Declaration
string this [int index] {get; set;}
//Example Method Declaration
bool Validate();
}
class MyControl : Fancy Control, IValidate
{
public MyControl()
{
data = "My Grid Data";
}
public bool Validate()
{
Console.Writeline("Validating ... {0}", data);
return true;
}
}
... MyControl myControl = new MyControl(); IValidate val = (IValidate)myControl; bool success = val.Validate(); ...
...
MyControl myControl = new MyControl();
if (myControl is ISerializable) // Avoids invalid cast runtime errors
{
ISerializable ser = (ISerializable)MyControl;
}
...
...
My Control myControl = new MyControl();
ISerializable ser = myControl as ISerializable;
if (null != ser)
{
// do stuff
}
...
You don't have to cast the object to its implemented interface to call that interface's methods. For example:
EditBox edit = new EditBox(); edit.Bind(); // use of interface without casting IDataBound bind = (IDataBound)bind; bind.Bind() // use of interface with casting
If two interfaces have the same member, we deal with the ambiguity in the following way:
interface ISerializable
{
void SaveData();
}
initerface IDataStore
{
void SaveData(); // This name is same as ISerializable's version
}
Implementing
class Test : ISerializable, IDataStore
{
void ISerializable.SaveData() {..}
void IDataStore.SaveData() {..}
}
Using
Test test = newTest(); ((ISerializable)test).SaveData(); ((IDataStore))test.SaveData();
Potential Problems:
Solution:
Combines two or moer interfaces such that the class need only implement the combined result
public interface ICombo: IDragDrop, I Serialize
{
//We can add more here if we like
}
I will only touch on the important/novel operators in this section
Works with System.Type .NET class
using System.Reflection;
Type t = typeof(Apple);
string className = t.ToString();
MethodInfo[] methods = t.GetMethods();
foreach(MethodInfo method in methods)
{
Console.WriteLine(method.ToString());
}
MemberInfo[] allMembers = t.getMembers();
foreach (MemberInfo member in allMembers)
{
Console.Writeline(member.ToString());
}
struct MyStruct
{
int i;
int j;
}
static unsafe public void ShowSize()
{
Console.WriteLine(sizeof(short));
Console.WriteLine(sizeof(MyStruct));
}
Foo test1 = new Foo(1);
Foo test2 = new Foo(2);
test1 = test2;
test1.i = 42;
Console.WriteLine("{0}", test2.i); // returns 42!
Expressions must be boolean (unlike c++ where it can be an int or null)
if (expresssion)
STATEMENT
else if (expression)
STATEMENT
else
STATEMENT
Switch statements work a bit different in C# then in C++ or java.
EXPRESSION can resolve to type: sbyte, byte, short, ushort, int, uint, long,
ulong, char, string or an enum based on one of these types (so long as it's
cast to one of the above types within the expression)
switch(EXPRESSION)
{
case(CONSTANT_EXPRESSION):
STATEMENTS;
break;
case(CONSTANT_EXPRESSION):
STATEMENTS;
break;
default:
STATEMENTS;
break;
}
C# does not allow fallthroughs (unlike C++ and Java), but it does support "combining case lables" such as the following:
switch((int)this.tender)
{
case (int)Tenders.Cash:
//dostuff;
break;
case (int)Tenders.Visa:
case (int)Tenders.Mastercard:
case (int)Tenders.Amex:
//domorestuff;
break;
}
Finally, the goto statement is also useable in a switch statement
switch((int)this.tender)
{
case (int)Tenders.ChargeOff:
//dostuff;
goto case (int)Tenders.Cash;
case (int)Tenders.Diners:
//dostuff;
break;
case (int)Tenders.Cash:
//dostuff;
goto default;
case (int)Tenders.Visa:
case (int)Tenders.Mastercard:
case (int)Tenders.Amex:
//domorestuff;
break;
default:
//domorestuff
break;
}
do
{
//statements;
} while (BOOLEAN-EXPRESSION);
Unlike c++, the scope of the variable i is restricted to the inner scope.
// outer scope
for (int i=0; i<10; i++)
{
//inner scope
}
// multiple variable example
for (int i = start, j=1; i <= end; i++, j++)
{
//inner scope
}
foreach(string word in myarray.words)
{
//do stuff
}
public void SomeMethod()
{
// Some error detected
throw new Exception();
// or throw new Exception("Thrown my SomeMethod");
}
public void Foo()
{
try
{
Bar();
}
catch (System.Exception e)
{
Console.Writeline(e.Message);
}
}
An exception should not be simply rethrown without doing some cleanup, otherwise there is little point!
...
try
{
Bar();
}
catch (Exception e)
{
// Free some resources
throw;
}
...
Finally ensures that a piece of code is always run, regardless of wether an exception is caught. For example, if an exception is thrown after a resource is allocated - We must deallocate the resource in the finally block
...
// allocate resources
try
{
// do stuff that could throw
}
catch (Exception e)
{
// exception handling
}
finally
{
// cleanup resources
}
...
Throwing an exception from a constructor is usefull because a constructor can't return anything!
try
{
AccessDatabase accessDB = new AccessDatabase();
}
catch (Exception e)
{
// Inspect caught exception;
}
public Exception();throw new Exception();
public Exception(String)
throw new Exception("Dammit, jim!");
...
catch (System.Exception e)
{
Console.WriteLine(e.Message);
}
proteted Exception(SerializationInfo, Streaming Context);public Exception( String, Exception );
...
throw new Exception(" ", new FormatException "Invalid Parameter Specified");
...
catch(Exception e)
{
Exception inner = e.InnerException;
Console.WriteLine(e.Message);
}
Console.WriteLine(e.StackTrace);=> at MyClass.Main()We can add a catch block for each type of exception that your code needs to handle. Note in the example below how we must handle derived exception classes first before the base classes. Otherwise, the derived blocks would be unreachable!
try
{
Foo(); // Can throw FooException;
Bar(); // Can throw BarException;
}
catch (FooException e)
{
Console.WriteLine(e.Message);
}
catch (BarException e)
{
Console.WriteLine(e.Message);
}
catch (Exception e)
{
Console.WriteLine("General Exception");
}
Reasons:
public class TestException:Exception
{
public TextException() : base() {}
public TextException(String message) : base(message) {}
public TestException(String message, Exception innerException) : base(message, innerException) {}
// Add custom methods here
}
Good practice:
public static Invoice operator+ (Invoice invoice1, Invoice invoice2)
{
// create a new invoice object obj
// combine contents into obj
// return obj
}
Overloadable operators
This is poorly treated right now. I will have to return to it. Basically, a
user-defined conversion allows structs or classes to be converted "automatically"
to other structs & classes by way of simple assignment statements. This
is done in a manner that seems a lot like overloading a "cast" operator.
Example of using two user-defined conversions are:
Farenheit f = 98.6F; //Constructor conversion Celcius C = (celcius)f; //Casting operator conversion
The two basic forms are:
public static implicit operator vonv-type-out (conv-type-in operand)public static explicit operator vonv-type-out (conv-type-in operand)A user-defined conversion can be used in two ways:
As a constructor
struct Celcius
{
...
public static implicit operator Celcius (float temp)
{
Celcius c;
c = new Celcius(temp);
return(c);
}
}
// usage: Celcius mytemp = 37.5F;
As casting operator:
struct celcius
{
...
public static implicit operator float(Celcius c)
{
return((((c.temp - 32) / 9) * 5 ));
}
}
// usage: float myTemp = myCelcius;
This is a similar concept to callbacks in other languages. Basically, it is a way of passing a function to another function via an itermediate container. The most quoted uses of this are:
It when not used as events (see later) is customary end deligate names with "Callback".
class Widget
{
private float myID;
...
// This is like a "method signature", or header.
// All callback functions must conform to this delegate definition
// to be useable!
public delegate void WidgetCallback(float widgetID);
// This method definition accepts a delegate as a parameter
public void ExecuteCallback(WidgetCallback aCallback)
{
...
// "aCallback" accepts a float, as defined by the delegate definition!
aCallback(myID); // this actually executed the callback function!
}
}
To use this defined delegate:
class app
{
...
// This is the function to eventually be called as a function pointer
public static void ButtonPressFunction(float buttonNumber)
{
Console.Writeline("Button {0} pressed.", someNumber);
}
public static void Main()
{
...
// The delegate is instantiated here, with the actual Callback Handler
// which is defined immediately above
Widget.WidgetCallback someCallback = new Widget.WidgetCallback(ButtonPressFunction);
...
MyWidget.ExecuteCallback(someCallback);
}
}
A better way is to instantiate the delegate as a static member:
class app
{
...
//Instantiate the delegate as a static member!
public static Widget.WidgetCallback buttonPressCallback = new Widget.WidgetCallback(ButtonPressFunction);
public static void ButtonPressFunction(float buttonNumber)
{
Console.Writeline("Button {0} pressed.", someNumber);
}
public static void Main()
{
...
MyWidget.ExecuteCallback(buttonPressCallback);
}
}
Sometimes, instantiating a delegate can be expensive, so it sometimes makes sense to do it lazily, by using a property:
class app
{
...
//Instantiate the delegate via a property
public static Widget.WidgetCallback buttonPressCallback
{
get
{
return new Widget.WidgetCallback(buttonPressCallback);
}
}
//...(define appCallback here)
public static void Main()
{
...
MyWidget.ExecuteCallback(app.buttonPressCallback);
}
}
Arrays of delegates can be made. This is usefull for:
Usage:
MyCallback[] delegateArray; // declare an array of delegates delegateArray = new MyCallback[10]; // creates space for 10 delegates delegateArray[6] = someDelegate; // adds a delegate to the array ... delegateArray[6](); // Invokes the callback
Underneath the hood, any delegate that returns void is a multicast
delegate; a linked list of delegates. This "linked list" understands
the operators + and - and may be used in two ways:
Say we have two callback functions, appHandler1 and appHandler2.
In the above Widget example, more than one callback can be executed, by simply
using the delegate as such:
...
public static void Main()
{
Widget.WidgetCallback myCallback1 =
new Widget.WidgetCallback(appHandler1);
Widget.WidgetCallback myCallback2 =
new Widget.WidgetCallback(appHandler2);
Widget.WidgetCallback myCallback = myCallback1 + myCallback2;
//or
myCallback1 += myCallback2;
//note: -= works as well!
MyWidget.ExecuteCallback(myCallback);
}
The individual delegates in the linked list are called sequentially, in the
order in which they were inserted onto the list (via + or +=). When the delegate
is "Invoked" (callback called) then ALL delegates in the linked list
are automatically called! In our example, aCallback(myID); calls
all callbacks registered!
In the case where the delegate has a return value, and we want to make use of that return value, then we may want to manually iterate through all the targets, This piece of code does the trick (note: to be used ONLY when the delegate has a return value):
if ( allCallbacks != null)
{
foreach (Widget.ButtonPressCallback bpCallback in allCallbacks.GetInvocationList())
{
accumulator += bpCalback();
}
}
The publish-subscribe design pattern is explicitly supported in C# by way of events: a class publishes an event that it can "raise". Any number of classes can then subscribe to the. Events are the formalized use of (multicast) delegates that support public [un]registration and private invocation. I look at them like a "container" for delegates, with a little more interface control.
Yes, we can technically do everything using just delegates but using the event interface, but by simply adding the "event" keyword we get:
This is similar conceptually to declaring a delegate instance variable. They
keyword "event" prefixing the instance declaration is
the only thing that is different on the implementation side. Events "hold" delegates.
By convention (read: it doesn't have to, but it is a recommended design pattern)
events have the pattern described below.
class WidgetEventArgs : EventArgs
{
public ButtonPressEventArgs(int id)
{
this.id = id;
}
public int id;
}
//The publisher
class Widget
{
...
public delegate void ButtonPressHandler (object source, ButtonPressEventArgs e);
public event ButtonPressHandler OnButtonPress;
}
This is as we have seen before with standard delegates, (used as instance variables)
except: assignment to event field disallowed (to avoid clobbering existing delegates)
and execution of event not supported (must be in class only!)
Example of proper use:
myWidget.OnButtonPress += new myWidget.ButtonPressHandler(someFunction);
myWidget.OnButtonPress -= someDelegate;
...
public void someFunction(object source, ButtonPressEventArgs e);
{
//do stuff
}
If we need to do more than just register another delegate when a client uses the+= and -= forms, we can do like this:
class Widget
{
...
public event ButtonPressHandler OnButtonPress{
add
{
counter += 1; // or whatever else you want
_myEventDelegateContainer += value;
}
remove
{
counter -= 1;
_myEventDelegateContainer -= value;
}
}
}
Threads are a way to concurrently execute different parts of a program at once. Carefull use of threads can increase a program's responsiveness and throughput. Careless use winds up with reduced throughput and inconsistent bad behaviour which is difficult to debug.
We will examine creating, killing and joining threads here. All creation and
management of threads is done through the System.Threading.Thread
class.
To create a thread, create an instance of the Thread class. The
thread class constructor takes a delegate as an arguement. The CLR provides
the ThreadStart delegate specifically for this purpose.
Example:
Using System;
Using System.Threading;
...
public void ConcurrentFunction()
{
//do stuff concurrently
}
...
// Create the threads here!
ThreadStart worker = new ThreadStart(ConcurrentFunction);
Thread t1 = new Thread(worker);
//Better yet
Thread t2 = new Thread( new ThreadStart (ConcurrentFunction) );
// Start the threads here!
t1.Start();
t2.Start();
Normally, threads die after running their course. You can ask a running thread
to kill itself by calling either its Interrupt() or Abort()
methods.
Interrupting a thread causes it to throw a ThreadInterruptedException,
which the thread can be caught in order to clean up any allocated resources.
Aborting a thread causes it to throw a ThreadAbortException.
In this case however, even if the method attempts to catch the ThreadAbortException,
the runtime won't let it. However, the thread's finally block will
still get executed, if present. Once you abort a thread, it cannot be restarted.
In that case, although you have a valid Thread object, you can't
do anything usefull with in in terms of executing code.
example:
...
public void ConcurrentFunction()
{
try
{
//do stuff concurrently
}
catch(ThreadAbortException e)
{
//This block never gets executed. CLR won't let it
}
catch(ThreadInterruptedException e)
{
// Free Resources if thread is interrupted.
}
finally
{
// Free resources in either case
}
}
...
Thread t1 = new Thread( new ThreadStart (ConcurrentFunction) );
t1.Start();
...
t1.Interrupt();
t2.Abort();
A thread can put itself to sleep for by a short time by calling the Thread.Sleep
method as such:
Using System.Threading; ... Thread.Sleep(100);
The parameter is the time in miliseconds to sleep. It can be passed as an integer
or a TimeSpan object. If you specify zero, then the thread simply gives up the
remainder of its timeslice. Note that you are not allowed to call Thread.Sleep
on any other thread other than the currently executing one. That's why Thread.Sleep
is a static method.
A thread can pause another thead using the Thread.Suspend method.
It is used as such:
Thread.Suspend is called on either the currently executing
thread (Thread.CurrentThread) or another thread.Thread.Resume
method.Thread.Resume will cause the thread to resume execution.t1.Join() method halts the current thread that the method was
called on, and waits for the thread t1 to complete.
To join thread t1 (onto the end of) to t2: t2.join();
Here are some good uses:
// Wait for all child threads to complete
foreach (Thread myThread in myThreads)
{
myThread.Join();
}
Console.Writeline("All my threads are done.");
// Makes sure a thread is dead before continuing
myThread.Interrupt();
myThread.Join();
Console.Writeline("Thread interrupted!");
Threads can be prioritized into five different levels using the Thread.Priority
property. The priorities that you can set this property are defined by an enum
as follows:
Thread.ThreadPriority.HighestThreadPriority.AboveNormalThreadPriority.NormalThreadPriority.BelowNormalThreadPriority.LowestFor example:
t1.Priority = ThreadPriority.Highest; t2.Priority = ThreadPriority.Lowest;
The default priority is, of course, Normal. Several threads running at the same priority get round robin scheduling. Be carefull when prioritizing some threads really high, as it may cause the GUI to become sluggish.
There are times in which we will want to control access to a resource, such
as a shared object, so that only one thread at a time can modify and use that
resource. The four synchronization mechanisms we will examine: The Interlock
class, the C# Lock statement, the Monitor class and
the Mutex class.
There some tasks that tasks that need synchronizing protection and seem to
arise so frequently that the .NET libraries include specific support for them.
The Interlocked class is meant to handle such functions. Incrementing
and Decrementing are some such common tasks. Here's an example of Interlocked
in action.
int count = 0;
...
public void DoStuffInAnotherThread()
{
Interlocked.Increment(ref counter);
...
}
In this case, Interlocked.Increment() expects a sincle parameter:
a reference to an int. Because int values are passed by value,
you use the ref keyword. More importantly, the increment is done
in a thread safe manner!
A lock marks a critical section of your code, providing synchronization to
an object you designate while the lock is in effect. It is a simpler form of
a Monitor, which is discussed later.
class Database
{
public void SaveData(string text)
{
lock(this)
{
//open database
//write database
//comitt database
//close database
}
}
}
The Monitor class takes synchronization one step further than
locks for more sophisticated control.
class Database
{
public void SaveData(string text)
{
Monitor.Enter(this)
//open database
//write database
//comitt database
//close database
Monitor.Exit(this)
}
}
Monitor.Enter(Object) and Monitor.Exit(Object) mark
entry into, and exit from the critical section.
In the middle of a monitor, if the command Monitor.Wait(this)
is called then the thread suspends (and frees the monitor) until another thread
makes a call to Monitor.Pulse(this). Once Pulse()
is called, then the suspended thread re-enters the critical section, continuing
on from where it called Wait().
In this scheme that threads can only suspend themselves!
Monitor.Wait(this) and Monitor.Pulse(this), must
BOTH be called within a "synchronized block", ie- they must be bound
by Monitor.Enter(this) and Monitor.Exit(this) statements.
The Mutex class is a runtime representation of the Win32 primitive.
They are a lot slower but have increased flexibility over what we have seen.
A mutex is an object with these possible constructors:
Mutex mutex = new Mutex(); //Current thread is owner of mutex Mutex mutex = new Mutex(false); // Does the thread creating the mutex want to own (lock) it? Mutex mutex = new Mutex(false, "My Mutex"); // As above but with name assigned