C Sharp Quick Ref
C Sharp Quick Ref
Integers 4. Collections
C# Alias Type (bits) Range
Value types (stored in the stack) sbyte SByte 8 -128 to 127 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
byte Byte 8 0 to 255
The value types in the .NET framework are usually small, frequently
used types. The benefit of using them is that the type requires very short Int16 16 -32,768 to 32,767
Arrays --size can be set by variable but can't change
little resources to get up and running by the CLR. Value types do not ushort UInt16 16 0 to 65,535 int[] integers = new int[20];
require memory to be allocated on the heap and therefore will not char Char 16 unicode 0 to 65,535 double[] doubles = new double[myVariable];
cause garbage collection. However, in order to be useful, the value int Int32 32 - + 2 billion
types (or types derived from it) should remain small - ideally below uint UInt32 32 0 to 4 billion ► Multidimensional
16 bytes of data. long Int64 64 - + 9 quintillion to int[,] test = new int[2, 3];
ulong UInt64 64 0 to 18 quintillion
►Value types are always copied (intrinsically) before being passed to ► Initialized at time of creation
a method. Changes to this new object will not be reflected back in the Floating-point
original object passed into the method. C# Alias .NET Type (bits) Precision Range int[] arr = new int[] { 24, 2, 13, 47, 45 };
float Single 32 7 digits E -45 to 38
►Value types do not /need/ you to call their constructor. They are double Double 64 15-16 digits E -324, 308 ► Arrays are passed by reference, not by value
automatically initialized. decimal Decimal 128 28-29 decimal - + E28
►Value types always initialize their fields to 0 or null. ► Arrays size will be arr.Length
Other predefined types
►Value types can NEVER be assigned a value of null (unless they C# Alias .NET Type (bits) Range // example: to copy first 3 elements of array:
are declared as Nullable Yypes) bool Boolean 32 true or false var sourceArray = new int[] { 11, 12, 3, 5, 2, 9, 28, 17 };
►Value types sometimes need to be boxed (wrapped inside an object Object 32/64 a pointer to an object var destinationArray= new int[3];
string String 16*length unicode, no upper bound.
object), allowing their values to be used like objects. Array.Copy(sourceArray, 0, destinationArray, 0, 3 );
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Reference types (stored in the heap)
enum Weekday { Monday, Tuesday, ... Sunday };
Reference types are managed very differently by the CLR. All
Weekday day = Weekday.Monday;
Array List
reference types consist of two parts: A pointer to the heap (which ► ArrayList before generics used boxing / unboxing.
contains the object), and the object itself. Reference types are slightly ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ This was slow & mix-and-match was not good practice.
heavier weight because of the management behind the scenes needed
to keep track of them. Reference types are nullable. struct is a light-weight object (value type), classes are ref types.
ArrayList myAL = new ArrayList();
Structs work best if < 17 bytes of data. If in doubt, use classes.
When an object is initialized, by use of the constructor, and is of a myAL.Add(1);
reference type, the CLR must perform four operations: struct Person myAL.Add("foo");
(1) The CLR calculates the amount of memory required to hold the {
object on the heap. (2) The CLR inserts the data into the newly public string name; ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
public int height;
created memory space. (3) The CLR marks where the end of the
space lies, so that the next object can be placed there. (4) The CLR
} List (generic) (IEnumerable, code used inside a method)
Person dana = new Person(); dana.name = "Dana Dev";
returns a reference to the newly created space. List<string> list = new List<string>();
This occurs every single time an object is created. However the struct Person // with constructor list.Add("Bruce is cool");
assumption is that there is infinite memory, therefore some { list.Add("Yes he is");
maintenance needs to take place - and that's where the garbage string name; int height;
collector comes in. string s = list[1];
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ public Person(string name, int height) int len = list.Count;
{ List methods include: Sort, IndexOf, Insert, Reverse,
Nullable Types -- If x.HasValue is true, it is not null this.name = name; AddRange, RemoveRange, RemoveAt, etc
int? x = 10; x = null; int?[] arr = new int?[10]; this.height = height;
} ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
int y = x; //-- will not compile
int y = (int)x; //-- compiles, but throws exception if x null } //-- create Array, convert to List, convert back
int y = x.Value; //-- same as above string[] myArr = { "dog", "zebra", "ant", "parrot" };
public class StructWikiBookSample List<string> list = new List<string>(myArr);
►If you perform an operation with null, the result will be null {
public static void Main() string[] myArr2 = list.ToArray() as string[];
?? operator -- defines default assignment if target is null: {
//-- sort Array and List
Person dana = new Person("Dana Developer", 60) ;
int d = c ?? -1; // d = c, unless c is null, then d = -1 } Array.Sort(myArr);
int g = e ?? f ?? -1 // g = e, if e null, then f, or -1 } list.Sort();
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
(Continued from 4. Collections) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ (continued from Dictionary)
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Dictionary -- key/value pairs (keys are unique) //--- show key/value pairs
Generic classes (Better to use generics)
Generic class
Non-generic
Meaning ► A dictionary is a hash table where the details and foreach (KeyValuePair<string, string> kvp in dict)
counterpart
Collection<T> CollectionBase The basis for the collections complexity are hidden. Hash tables are faster than {
Comparer<T> Comparer
Compares two objects for search trees or other lookup structures. Why is this? WriteLine(kvp.Key + ", " + kvp.Value);
equality }
Dictionary<K,V> Hashtable
A collection of name-value Let's assume you want to fill up a library with books
pair and not just stuff them in there, but you want to be able
List<T>
A dynamic resizable list of //--- Create lists using dict keys or values
ArrayList
items to easily find them again when you need them. So, you
Queue<T> Queue FIFO list decide that if the person that wants to read a book var list1 = dict.Keys.ToList();
Stack<T> Stack LILO list
knows the title of the book, the person, with the aid of var list2 = dict.Values.ToList();
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ the librarian, should be able to find the book easily and foreach (string s in list1) { WriteLine (s); }
LinkedList -- allows constant time for insert or quickly. foreach (string s in list2) { WriteLine (s); }
remove, but only sequential access to elements list1.Sort(); //-- easy to sort
So, how can you do that? Well, obviously you can keep
LinkedList<string> LL = new LinkedList<string>(); some kind of list of where you put each book, but then //-- Sort using LINQ
LL.AddLast("aaa"); you have the same problem as searching the library, you var items = from x in dict orderby x.Value select x;
LL.AddFirst("bbb"); need to search the list. Granted, the list would be foreach(KeyValuePair<string, string> pair in items)
LL.AddLast("ccc"); smaller and easier to search, but still you don't want to { WriteLine (pair.Key + ", " + pair.Value); }
LL.AddLast("ddd"); search sequentially from one end of the library (or list)
to the other. //-- Sort using Lamda
LinkedListNode<string> node = LL.Find("ccc"); foreach (var pair in dict.OrderBy(p => p.Key))
LL.AddBefore(node, "hello there beautiful"); You want something that, with the title of the book, can { WriteLine(pair); }
Other methods include: AddAfter, Average, give you the right spot at once, so all you have to do is
Contains, Distinct, Find, FindLast, Max, Min, just stroll over to the right shelf, and pick up the book. //-- update value for a given key
OrderBy, Remove, ToList, etc So you devise a clever method: You take the title of the dict["cn"] = "People's Republic of China";
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ book, run it through a small computer program, which
spits out a shelf number and a slot number on that shelf. //-- xx
Queue -- First In, First Out (FIFO) This is where you place the book. x
Queue<string> q = new Queue<string>(); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Dictionary<string, string> dict
q.Enqueue("aaa");
= new Dictionary<string, string>();
Don't bother with:
q.Enqueue("bbb"); (1) any of the non-generic collections or
q.Enqueue("ccc"); (2) SortedDictionary, SortedList, SortedSet or
WriteLine(q.Dequeue()); //-- removes and returns dict.Add("de", "Germany");
dict.Add("es", "Spain"); (3) Concurrent versions
WriteLine(q.Peek()); //-- returns, does not remove
dict.Add("uk", "Britain"); ► Some of these are similar to dictionary as they make
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ dict.Add("fr", "France"); use of key-value pairs, but are sorted or do other things
Stack -- Last In, First Out (LIFO) dict.Add("cn", "China"); a bit different.
Stack<string> stack = new Stack<string>(); WriteLine(dict["cn"]); //-- shows China ► The non-generic stuff should be considered
stack.Push("xxx"); WriteLine(dict["fr"]); //-- shows France deprecated. Don't use unless necessary for maint work
stack.Push("yyy"); on old code.
stack.Push("zzz"); ► Below are examples of what you can do to filter, sort ► Also--don't bother with Concurrent versions of these
WriteLine(stack.Pop()); //-- removes and returns and view dictionary keys and values. collections unless you are using multiple threads
WriteLine(stack.Peek()); //-- return, don't remove
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
5. Classes static vs. instantiated
► fields, methods and classes can be static
polymorphism
public class Animal
-- overriding what you Inherited
► Fields can be assigned in class declarations (compiler ► static class can't be instantiated or derived from {
will automatically move initialization to constructor) ► static class can contain only static methods and fields public virtual string talk() { return "Hi"; }
public string sing() { return "lalala"; }
► Below is class with constructors ► static is good enough if the class holds no state info }
► a static method can't access non-static class members
public class Employee public class Cat : Animal
{ Car ford = new Car(); // instantiating a non-static class {
public Employee() MyStaticClass.MyMethod(); // invoking method from static class public override string talk() { return "Meow!"; }
{ }
Console.WriteLine("Constructed without parameters"); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
} encapsulation -- restrict access for safety -- public class Dog : Animal
{
public Employee(string strText) public / private -- private methods and fields can only be public override string talk() { return "Woof!"; }
{ accessed from other class methods, not from outside the class. public new string sing() { return "woofa woofa woooof"; }
Console.WriteLine(strText); Classes, methods and fields are private by default. }
}
}
Enums and structs are public by default. public class Polymorphism
protected -- like private except derived classes can access {
► Constructors can call each other: public Polymorphism()
internal -- restricted, only members of the class can access. {
public class Employee An internal class is not accessible from an external program. write(new Cat());
{ write(new Dog());
(This is only needed in larger, more complex programs)
public Employee(string text, int nbr) { ... } }
protected internal -- combination of protected OR internal public void write(Animal a)
// calls above with user text and default nbr {
public Employee(string text) : this(text, 1234) { ... } sealed -- class that cannot be derived from WriteLine(a.talk());
}
// calls above with default text ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ }
public Employee() : this("hello") { ... }
} inheritance (derived class B inherits from parent A) another example
public interface Animal
this is used to refer to member of the current instance of Class A { ... } {
class. It cannot refer to static field or method or be inside a string Name { get; }
Class B : A { ... } }
static class. It is often not required and may be infered by the
compiler, but it clarifies intent to human readers. example: public class Dog : Animal
base is used in constructors of a child class to refer to the {
public class BaseClass
instance of the parent class public string Name { get { return "Dog"; } }
{
}
public string HelloMessage = "Hello, World!";
class A {public string myStr = "hello"; } }
public class Cat : Animal
class B : A {
public class SubClass : BaseClass
{ public string Name { get { return "Cat"; } }
{
public string myStr = "world"; }
public string ArbitraryMessage = "Uh, Hi!";
public void MyWrite() }
{ Console.WriteLine( base.myStr + " " + this.myStr ) } public class Test
} { static void Main()
public class Test
{
{
public class B : A Animal animal = new Dog();
static void Main()
{ Animal animal2 = new Cat();
{
// constructor for class B (constructor for A executed first) Console.WriteLine(animal.Name);
SubClass subClass = new SubClass();
public B () : base () { } Console.WriteLine(animal2.Name);
Console.WriteLine(subClass.HelloMessage);
} }
}
}
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ }
(Continued from 5. Classes) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ (continued from Extension Methods)
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ► Virtual methods are subject to override
public static class ExtensionMethods
get or set class properties using accessors {
class A
► The variable below is too easy to access from outside { public static string UppercaseFirstLetter(this string value)
the class, this lacks discipline, invites trouble. public virtual void Act() { } {
} if (value.Length > 0)
class Culture {
{ class B : A char[] array = value.ToCharArray();
public string Language; { array[0] = char.ToUpper(array[0]);
} return new string(array);
public override void Act()
}
{ Console.WriteLine("Perl.Act"); }
► Accessors below can be used as gatekeepers or return value;
}
}
modify read/write, maintain maximum control, etc.
}
► Abstract classes require a derived class, and cannot
class Culture be directly instantiated. They can contain abstract ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
{ methods, which require override methods. ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
public string Language { get; set; } abstract class A partial -- partial class can be split across more than one file
} {
public int ok;
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
-- or -- public abstract void MyMethod(); nested -- like it sounds, one class nested inside another
class Culture }
class A
{ {
private string lang; class B : A
{ public int v1;
public string Language
{ public override void MyMethod()
{ public class B { public v2; }
get { return "my " + lang; } Console.WriteLine("this is cool"); }
set { lang = value; } base.ok++;
} } class Program
} } {
static void Main()
{
protected set //-- permission only to derived classes interface -- Similar to abstract class. Contains A a = new A();
classes, methods and properties (but not fields). Widely a.v1++;
► As a principle, anything that you can keep from used (behind the scenes) to implement work with
allowing other code to touch, should be kept that way. A.B ab = new A.B();
IEnumerable and foreach. Don't worry about it. ab.v2++;
If other classes will need to view something in your class, you'll need
to expose a getter, but not a setter. They also allow you to perform ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ }
calculations or validations before returning or setting data. For }
example, if you have some integer value that should be within some
Extension methods -- Custom extension ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
range, in your setter you can check to make sure this condition is met methods are very cool ! You create a static class that uses the
before actually updating your value. this keyword, and it acts like an instance method for
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ whatever you want to extend. See example below.
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
--[]--