Areas
Conventions
- Don't give type and namespace the same name [1].
Language Features
Lazy Class
public class Awesomeness
{
private Lazy<AwesomeObject> _ourAwesomeObject = new Lazy<AwesomeObject>(() =>
{
var awesomeObject = new AwesomeObject();
//do stuff here to build your awesomeObject
return awesomeObject;
});
public AwesomeObject OurAwesomeObject
{
get { return _ourAwesomeObject.Value; }
}
}
Tuples (4.0) and Type Inferrence (3.0)
The Tuple object in 4.0 can handle up to 8 parameters.
var data = new Tuple<string,int>(“John Doe”, 42); //can't use type inferrence with constuctors.
var data = Tuple.Create<string,int>(“John Doe”, 42);
var data = Tuple.Create(“John Doe”, 42); //same as above but using type inferrence
string name = data.Item1;
int age = data.Item2;
"A Tuple is often used to return multiple values from functions when you don’t want to create a specific type. Although not a perfect analogy, this is somewhat similar to how one uses Anonymous Types, except that Anonymous Types cannot go outside a method boundary like a Tuple."
http://www.davidhayden.me/2009/12/tuple-in-c-4-c-4-examples.html
Parallel Programming
Parallel.For (0, count, delegate int(i)
{
//for loop body
});
//control passed here once all parallel iterations complete
Parallel.ForEach (arr, (string item) =>{
// Do something
});
Extension Methods
Yield
Shortening and Widening Conversions
int i = 1;
double d = 1.0001;
d = i; //implicit widening conversion.
class MyInt : IConvertable {
int Value;
//Use the following for when a cast is required to cast MyInt to int i.e (int)MyInt
public static explicit operator int(MyInt i) {
return i.Value;
}
//Use the following for when a cast is not required to convert int to MyInt e.g MyInt i = 5;
public static implicit operator MyInt(int i) {
return new MyInt(i);
}
public bool IConvertable:ToBoolean(IFormatProvider provider) {
return Convert.ToBoolean(Value);
}
...
}
Convert.ToBoolean(myInt);
Casting
The Prefix cast:
GenericType g=...;
SpecificType t=(SpecificType) g;
The as cast:
GenericType g=...;
SpecificType t=g as SpecificType;
- Returns a null when the variable you are trying to convert is not of the requested type or in it's inheritance chain, instead of throwing an exception.
- Using as will not perform user-defined conversions, such as implicit or explicit conversion operators, which casting syntax will do.
- Faster.
Events / Delegates
public class MyEventArgs : EventArgs { } //EventArgs is an empty class used for events with no data
//A Multicast delegate is a delegate returning void, and multiple instances can be chained to events with += and removed with -.
public delegate void MyEventHandler(object sender, MyEventArgs e);
public event MyEventHandler MyEvent; //or use EventArgs<MyEventArgs> instead of MyEventHandler
if (MyEvent != null) { //null if there are no handlers
MyEvent(this, new MyEventArgs());
}
MyClass.MyEvent += new MyEventHandler(MyHandleEvent);
Action<T> and Func<TResult>
static void Main(string[] args)
{
int result = DoStuffToSomething<DateTime, DateTime, int>(
DateTime.Now,
DateTime.MaxValue,
date => {
Console.WriteLine(date.ToShortDateString());
Console.WriteLine(date.ToLongTimeString());
},
(date1, date2) => (date2 - date1).Days);
Console.WriteLine(result.ToString() + " days before .NET DateTime explodes.");
Console.Read();
}
static R DoStuffToSomething<T1, T2, R>(T1 something, T2 somethingElse, Action<T1> myAction, Func<T1, T2, R> myFunction)
{
myAction(something);
return myFunction(something, somethingElse);
}
Prints:
22/04/2010
12:16:24 p.m.
2918175 days before .NET DateTime explodes.
More info:
Note there are other overloads for providing more parameters, e.g:
- Action<T1, T2, T3>
- Func<T1, T2, T3, TResult>
Lambda expressions
Formatting
string.Format("Price: {0}",price);
string.Format("Price: {0,5}",price); //right align
string.Format("Price: {0,-5}",price); //left align
Value Types
- System.ValueType : System.Object
These are copied and passed around on the stack.
| keyword | Type | Bytes | Range |
| sbyte | System.SByte | 1 | -128-127 |
| byte | System.Byte | 1 | 0-255 |
| short | System.Int16 | 2 | -32768-32767 |
| int | System.Int32 | 4 | -2,147,483,648-2,147,483,647 |
| uint | System.UInt32 | 4 | |
| long | System.Int64 | 8 | |
| float | System.Single | 4 | |
| double | System.Double | 8 | |
| decimal | System.Decimal | 16 | |
| char | System.Char | 2 | |
| bool | System.Boolean | 1 | |
| System.DateTime | 8 | |
Note int and double are optimised by the .NET framework and hardware
Structs
Structs are value types (copied entirely onto stack when passed as parameter (unless the ref keyword is used) or when assigned to another - not just memory pointer)
Use structs if:
- Instance size less than 16 bytes.
- Not frequently changed.
- Not cast (boxed) to a reference type.
Hint: override ToString(), Equals & GetHash in structs to prevent boxing.
Enums
public Enum Titles { Mr, Mrs, Ms, Dr }
Reference Types
Reference types are stored in the heap and are cleaned up by the garbage collector when there are no more references to the object.
GC.Collect(); //to force a garbage collection
//If a value type has been boxed into a reference type, you can find out if it is a value type by.
object o = 5; //boxing
o.GetType().IsValueType;
int i = (int)o; //unboxing
i.ToString(); //boxing (because the ToString() method exists on Object)
//Note that boxing and unboxing both have performance hits and should not be done in loops.
Strings are immutable (can't be changed)
Strings have operator overloads to cause value type behavior:
- + Joins two strings to create a new string
- == True if the string contents are the same
- = Copies the contents of the string to the new string, called when passed as a parameter by value.
Nullable
//Note that a nullable value type is still passed around as a value type.
bool? b = null;
//or
Nullable<bool> b = null;
b.HasValue
b.Value
if (b == null) {...}
Arrays
int[] ar = { 1, 3, 2 };
Array.Sort(ar);
Exceptions
Exception
.Message
.StackTrace
.Source (library)
.Data (user defined name/value pairs)
throw new Exception("Exception message");
//For defining custom exception classes to throw. Message / Data is overridden. Simply extended Exception is now recommended however.
ApplicationException : Exception