1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
using System; interface IAuthentication { void login(); void logout(); } // class AzureAuth: IAuthentication { private void initAzureStuff() { Console.WriteLine("utilities to ...init Azure stuff"); } public void login() { Console.WriteLine("AzureAuthention LOGIN code"); } public void logout() { Console.WriteLine("AzureAuthention LOGOUT code"); } } class AWSAuth: IAuthentication { private void initAWSStuff() { Console.WriteLine("Amazon init stuff...."); } public void login() { Console.WriteLine("AWS LOGIN code"); } public void logout() { Console.WriteLine("AWS LOGOUT code"); } } public class Program { public static void Main() { Console.WriteLine("Hello World"); // we can switch in and out components that adapt to the interface // like so // AzureAuth autho = new AzureAuth(); AWSAuth autho = new AWSAuth(); // Does not matter whether we use Azure, or AWS // all we care about is login and logout autho.login(); autho.logout(); } } |
Boxing
Boxing
- The first two lines of code declare and initialize value type variable i and reference type variable oi.
- In the third line of code, you want to assign the value of variable i to oi. But oi is a reference type variable and must be assigned a reference to an object in the heap.
- Variable i, however, is a value type and doesn’t have a reference to an object in the heap.
- Creating an object of type int in the heap
- Copying the value of i to the int object
- Returning the reference of the int object to oi to store as its reference
The system therefore box the value of i by doing the following:
Memory is allocated on the heap that will contain the value type’s data and the other overhead necessary to make the object look like
every other instance of a managed object of reference type .
The value of the value type is copied from its current storage location into the newly allocated location on the heap.
The result of the conversion is a reference to the new storage location on the heap.
1 2 3 4 5 6 |
int i; object oi; i = 42; // Boxing oi = i; |
Unboxing
What is UnBoxing Conversion?
Unboxing is the process of converting a boxed object back to its value type.Unboxing is an explicit conversion.
The system performs the following steps when unboxing a value to ValueTypeT:
It checks that the object being unboxed is actually a boxed value of type ValueTypeT.
It copies the value of the object to the variable.
Lambda
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; int [] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 }; //num => num % 2 == 1, means get any number with modulo of 1 (AKA odd number) //in our case, its 1, 1, 3, 5, 13, 21. //Average() means add all of these numbers up and divide by how many there are // 1+1+3+5+13+21/6 = 7.333333 double averageValue = fibNum.Where(num => num % 2 == 1).Average(); Console.WriteLine(averageValue); |
Search for string in string array
lambda
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
string [] arr1 = new string[] { "otwone", "two", "threetwo", "fotwour", "five", "two" }; foreach (string s in arr1.Where( x => { if(x.Contains("two")) { return true; } return false; } )) Console.WriteLine(s); |
Result:
otwone
two
threetwo
fotwour
two
LinQ
1 2 3 4 5 6 7 8 9 10 |
string [] arr1 = new string[] { "otwone", "two", "threetwo", "fotwour", "five", "two" }; var query = from arr in arr1 where arr.Contains("two") select arr; foreach(var s in query) { Console.WriteLine("{0}", s); } |
Result:
otwone
two
threetwo
fotwour
two
Determine if any ints are larger or less
Lambda
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 }; foreach (int i in source.Where( x => { if (x <= 3) { Console.WriteLine("less than or equal to 3: {0}",x); return true; } else if (x >= 7) { Console.WriteLine("more than or equal to 7: {0}",x); return true; } return false; } )) Console.WriteLine(i); |
Result:
less than or equal to 3: 3
3
more than or equal to 7: 8
8
less than or equal to 3: 1
1
more than or equal to 7: 7
7
more than or equal to 7: 9
9
less than or equal to 3: 2
2
more than or equal to 7: 8
8
Find age in Array of Structs
linQ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public class Program { struct Item { public int a; public string b; public Item(int a, string b) { this.a = a; this.b = b; } }; public static void Main() { Item [] people = { new Item( 12, "little todd" ), new Item( 13, "little timmy" ), new Item( 36, "Ricky"), new Item( 33, "zelda") }; var oldQuery = from person in people where (person.a >= 30) select person; foreach(var s in oldQuery) { Console.WriteLine("old person {0}", s.b); } } } |
Delegates for c#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; public class Program { public delegate bool D(); public delegate bool D2(int i); class Test { D del; //private, no accessible public D2 del2; //public, accessible // method public void TestMethod(int input) { //method scope Console.WriteLine("TestMethod start"); int j = 0; //delegate definition in method //has access to outer scope del = () => { Console.WriteLine("del delegate definition start"); j = 10; return j > input; }; //accesses outer scope int j and input del2 = (x) => { Console.WriteLine("del2 delegate definition start"); // x is passed in as parameter // j is declared outside scope. // input was passed in earlier Console.WriteLine("x is {0}, j is {1} input is {2}", x, j, input); return x == j; }; Console.WriteLine("j = {0}", j); bool boolResult = del(); //j is local scope Console.WriteLine("j = {0}. b = {1}", j, boolResult); } } public static void Main() { Test test = new Test(); test.TestMethod(5); //delegate del2, still has copy of local varaibles j and input from TestMethod. bool boolResult = test.del2(10); Console.WriteLine(boolResult); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
using System; public class Program { // declare the delegate delcaration // it takes an int as a parameter // it returns an int public delegate int DelType(int i); // we are a static object, thus, methods must match static status public static void displayMagicNumber(DelType dd) { Console.WriteLine("{0}", dd(886)); } public static void Main() { // declare a delegate variable // assign it to a delegate definiton // where it takes and returns an int DelType dd = delegate(int value) { return (value +2); }; Console.WriteLine("{0}", dd(10)); displayMagicNumber(dd); } } |
Doubly Linked List
Situations for using a Doubly Linked list would be
- deck of cards
- browser cache
- Metro
A new node’s previous points left, and next points right. When we add a new node, we pass in the linked list’s tail into the new Node’s constructor.
The new Node will re-wire it so that its previous points to the last node of the linked list (via the tail).
Then have the next of the last node point to the new Node.
Then, the linked list will proceed to re-assign the tail to the new node. Thus, completing the push.
Also, each node is connected with each by 2 traits:
- The first node’s next points to the second node. The first node’s previous points to the node on its left side. (or bottom, if you are looking at it vertically)
- The second node’s previous points to the first node. And its next points to the node on its right side. (or top, if you are looking at it vertically)
Getter/Setters
Getter setter is done by first declaring a name that matches your property but with a capital first letter. Then, you use keywords get and write a function for when you retrieve the property.
Use keyword set to write a function where you assign another value to your property. The incoming value is designated as keyword “value”. The value keyword is a contextual keyword, that is, it has a different meaning based on its context.
Inside a set block, it simply means the value that the programmer has set it to.
Outside of a set block, you can use value as a variable identifier, as such:
int value = 5;
1 2 3 4 5 6 7 8 9 10 11 |
public int Count { get { Console.WriteLine("-- DoublyLinkedList - Count, getter --"); return count; } set { Console.WriteLine("-- DoublyLinkedList - Count, setter --"); count = value; } } |
You’d use it like this:
myList.Count = 222;
Doubly Linked List source
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
using System; public class Program { //note that previous points left, and next points right //create reference type Node public class DoublyLinkedNode { public DoublyLinkedNode next; public DoublyLinkedNode previous; public object data; // constructors public DoublyLinkedNode(Object newData) { this.previous = null; this.data = newData; this.next = null; } //if tail comes in, our previous, pointing left, would now point to tail, AKA end of the list //then tail.next takes on this. Thus, we just attached this Node to the end of the list public DoublyLinkedNode(object newData, DoublyLinkedNode previous) { this.data = newData; this.previous = previous; previous.next = this; } // data getter/setter public Object Data { get { return data; } set { data = value; } } // next getter/setter public DoublyLinkedNode Next { get { return next; } set { next = value; } } // next getter/setter public DoublyLinkedNode Previous { get { return previous; } set { previous = value; } } } //end of DoublyLinkedNode public class DoublyLinkedList { private DoublyLinkedNode head; private DoublyLinkedNode tail; public int count; // in order to use the getter/setter, call Count public int Count { get { Console.WriteLine("-- DoublyLinkedList - Count, setter --"); return count; } set { Console.WriteLine("-- DoublyLinkedList - Count, getter --"); count = value; } } // in order to use the getter/setter, call Head public DoublyLinkedNode Head { get { Console.WriteLine("DoublyLinkedList - Head, getter"); return head; } set { Console.WriteLine("DoublyLinkedList - Head, setter"); head = value; } } //constructor public DoublyLinkedList() { Console.WriteLine("-- DoublyLinkedList Constructor --"); this.head = null; this.tail = null; this.count = 0; //use 'this' to distinguish in case there are same variable name Console.WriteLine("-- DoublyLinkedList Constructor Done --"); } public void Add(object item) { if (this.head==null) { this.head = new DoublyLinkedNode(item); this.tail = this.head; } else { // incoming item should now be at the end of the list. // we pass in the tail so that the Node can sort out the attachment // 1) assign the data // 2) previous of new node points to this.tail, aka the last Node // 3) this.tail.next points to new Node DoublyLinkedNode newItem = new DoublyLinkedNode(item, this.tail); // 4) finally, reassign tail to this new Item this.tail = newItem; } } public void printForward() { Console.WriteLine("printForward Start----"); for (DoublyLinkedNode temp = this.head; temp != null; temp = temp.next) { Console.WriteLine("print: {0}", temp.data); } Console.WriteLine("printForward End----"); } public void printBackward() { Console.WriteLine("printBackward Start----"); for (DoublyLinkedNode temp = this.tail; temp != null; temp = temp.previous) { Console.WriteLine("print: {0}", temp.data); } Console.WriteLine("printBackward End----"); } } //end of DoublyLinkedList public static void Main() { Console.WriteLine("Hello World"); DoublyLinkedList myList = new DoublyLinkedList(); Console.WriteLine("{0} ", myList.Count); //uses the getter myList.Count = 222; Console.WriteLine("{0} ", myList.Count); //uses the getter myList.Add("haha"); myList.Add("hehe"); myList.Add("hoho"); myList.printForward(); myList.printBackward(); } } |
queue
For queues, we append new node at the tail end, and the tail take on its next.
The head pointer stays in place at the first node. When we execute something, we pop from the queue, and the head moves to next.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
using System; public class Program { //create reference type Node public class Node { public Node next; public Object data; public Node(Object newData, Node newNext) { next = newNext; data = newData; } } public class Queue { private Node head; //head points to the beginning of the queue. We pop by using the head. private Node tail; //tail points to the end of the queue. We append using the tail // public void push(Object newData) { if((head == null) && (tail == null)) { head = tail = new Node(newData, null); Console.WriteLine("+ pushed {0} onto the Queue", newData); return; } tail.next = new Node(newData, null); tail = tail.next; Console.WriteLine("+ pushed {0} onto the Queue", newData); } public void pop() { if(head != null) { Node toRemove = head; head = head.next; Console.WriteLine("- popped {0} onto the Queue", toRemove.data); toRemove.data = null; toRemove.next = null; } else { Console.WriteLine("Can't pop anymore, Queue is empty"); } } public void print() { Console.WriteLine("************ START ************"); for (Node temp = head; temp != null; temp = temp.next) { Console.WriteLine(temp.data); } Console.WriteLine("************ END ************"); } } public static void Main() { Console.WriteLine("Hello World"); GBTU g = new GBTU(); g.BTech(); //reference type LinkedList Queue myList = new Queue(); myList.push("Ricky"); myList.push("Lily"); myList.push("Sophia"); myList.print(); myList.pop(); myList.print(); myList.pop(); myList.pop(); myList.print(); myList.pop(); } } |
Stack
Stack appends (or pushes) at the end. And pops at the end also. hence, all we need is one pointer to do that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
using System; public class Program { //create reference type Node public class Node { public Node next; public Object data; public Node(Object newData, Node newNext) { next = newNext; data = newData; } } public class Stack { private Node head; //variable 'head' reference type stores references (addresses) // public void push(Object newData) { head = new Node(newData ,head); } public void pop() { if(head != null) { head = head.next; } else { Console.WriteLine("Can't pop anymore, stack is empty"); } } public void print() { Console.WriteLine("-------- START --------"); for (Node temp = head; temp != null; temp = temp.next) { Console.WriteLine(temp.data); } Console.WriteLine("------ END -------"); } } public static void Main() { Console.WriteLine("Hello World"); //reference type LinkedList Stack myList = new Stack(); myList.push(88); myList.push(99); myList.push(120); myList.print(); myList.pop(); myList.print(); myList.pop(); myList.pop(); myList.print(); myList.pop(); } } |
Abstraction
Abstraction
Abstraction is the tactic of stripping an idea or object of its unnecessary accompaniments until you are left with its essential, minimal form. A good abstraction clears away unimportant details and allows you to focus and concentrate on the important details.
- Declare the abstract class, then use keyword abstract to define your abstraction methods
- Create a class, and conform to that abstraction
- Once conformed, use keyword override to implement for that abstraction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class Program { //abstract means that who ever extends this abstract //must implement the abstraction public abstract class university { //abstraction 1 public abstract void BTech(); } public class GBTU : university { public override void BTech() { Console.WriteLine("I am BTech"); } } public static void Main() { Console.WriteLine("Hello World"); GBTU g = new GBTU(); g.BTech(); } } |
Classes and Structs
http://stackoverflow.com/questions/521298/when-to-use-struct
Struct
Struct is a blueprint for a value – no identity, no accessible state, no added behavior (methods).
Variables of struct type are strictly called values.
Value types are the types found at the lowest level of a program. They are the elements used to build larger software entities. Value types can be freely copied and exist on the stack as local variables or as attributes inside the objects they describe.
Consider defining a structure instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.
Do not define a structure unless the type has all of the following characteristics:
It logically represents a single value, similar to primitive types (integer, double, and so on).
It has an instance size smaller than 16 bytes.
It is immutable.
It will not have to be boxed frequently.
notes –
In addition, realize that when a struct implements an interface – as Enumerator does – and is cast to that implemented type, the struct becomes a reference type and is moved to the heap.
Whenever you don’t need polymorphism, want value semantics, and want to avoid heap allocation and the associated garbage collection overhead. The caveat, however, is that structs (arbitrarily large) are more expensive to pass around than class references (usually one machine word), so classes could end up being faster in practice.
Class
A class is a blueprint for an object.
It has identity. Identity is an instantiated object with its own state.
It has accessible state (private variables), added behavior (methods).
Types represented by classes are called reference types.
Reference types are the types found at the higher levels of a program. They are built from smaller software entities. Reference types generally cannot be copied, and they exist on the heap.
If you copy a struct, C# creates a new copy of the object and assigns the copy of the object to a separate struct instance. Thus, we’re dealing with the object itself.
However, if you copy a class, C# creates a new copy of the reference to the object and assigns the copy of the reference to the separate class instance. We’re dealing with the address here.
Passing Blocks as parameter to other Blocks
What we’re trying to accomplish
Say you have class BackgroundTask that retains a block elsewhere and will run it in your app like so:
1 2 3 4 5 6 7 8 9 10 11 |
@interface BackgroundTask () { } @property (copy, nonatomic) OnBackgroundTask task; ... ... -(void)run { self.task(); // execute that task } |
The block of code that property task points to is something like this:
1 2 3 4 5 6 7 8 9 10 |
for(int i = 0; i < 20; i++) { NSLog(@"%s - processing...%d", __FUNCTION__, i); if(i == 8) { //want to reply to BackgroundTask to do something break; } } |
So somewhere within the task, when we reach a certain point, we want to communicate to Background task that we want it to do say, do some clean up. How do we communicate back to BackgroundTask?
Solution – Pass in a reply block
1) declare a block with a block parameter
1 |
typedef void (^OnBackgroundTask) (CleanUpBackgroundTask cleanup); |
This means that we declare a block called OnBackgroundTask, which returns void. However, it does take 1 parameter of type CleanUpBackgroundTask.
where CleanUpBackgroundTask returns void and takes no parameters
1 |
typedef void (^CleanUpBackgroundTask) (); |
We will be using CleanUpBackgroundTask to communicate back to BackgroundTask.
2) declare the reply block with code definition, then pass it into the original block during the call
So when using the code, you provide a block of code for the task like so:
1 2 3 4 |
[[BackgroundTaskManager singleton] addBackgroundTask:^(CleanUpBackgroundTask cleanUp) { // your code task here cleanUp(); }]; |
self.task now points to the block of code you just provided. cleanup block currently is not defined. We can define it right before you call self.task and pass it in.
1 2 3 4 5 6 7 8 9 |
CleanUpBackgroundTask backgroundTaskCleanUp = ^{ NSLog(@"%s ----------- OnFinishTask BLOCK for %@----------------", __FUNCTION__, self.taskName); [self cleanup]; }; ... ... self.task(backgroundTaskCleanUp); // code 'task' will now run |
At this point, the task code is called, your code task will run, and the cleanUp() will naturally be called within code ‘task’.