# C\#

#### Data Types:

Data types in C# are referred to as "value types" and "reference types".

When a value type is declared, the data is stored in the memory location of the variable.  \
When a reference type is declared, the data is stored somewhere else in memory and the variable contains a pointer it.

* Reference types are always allocated in heap memory,&#x20;
* value types can be allocated on the heap or on the stack depending on where they're declared. &#x20;

If a value type is declared inside a method, then it's stored on the stack.  If it's declared in a class, then the data is stored on the heap.  This is because a class is a reference type, which must always be stored on the heap. &#x20;

Value types include `int`, `byte`, `bool`, and `char`.  Reference types include `string`, `arrays` and `class`.

#### Integers:

An integer to be negative, it should be declared as a "signed" integer. Otherwise, it can be "unsigned". Unsigned integers can be larger than signed integers because we're not wasting a "sign" bit. We can allocate different sizes for an integer in multiples of 8 bits: 8, 16, 32 and 64 bits.

| Keyword | Size            |
| ------- | --------------- |
| sbyte   | Signed 8-bit    |
| byte    | Unsigned 8-bit  |
| short   | Signed 16-bit   |
| ushort  | Unsigned 16-bit |
| int     | Signed 32-bit   |
| uint    | Unsigned 32-bit |
| long    | Signed 64-bit   |
| ulong   | Unsigned 64-bit |

A floating point is a number that can have decimal places, 8.2, 3.14, etc. declaring a float or double, the letter `F` or `D` should be appended to the value. There are three types (all of which are signed):

| Keyword | Size     |
| ------- | -------- |
| float   | 4 bytes  |
| double  | 8 bytes  |
| decimal | 16 bytes |

A `bool` is a true or false value

A `char` is a single letter or number, represented by an integer

The `array` and `tuple` are both types of collections

An array can hold multiple values of a single data type; whereas a tuple can hold multiple values but of various data types

A tuple is declared using parenthesise for both the data types and initial values; and instead of accessing a tuple index via square brackets, we use the period, `.`.  Each item is given a name like `Item1`, `Item2`, etc. Can use a concept called "deconstruction" to assign friendly variable names to your elements.

```
(string, string, int) tuple = ("duck", "goose", 2);
(string firstbird, string secondbird, int numerofbirds);
```

One way is via interpolation, denoted by a prepended `$`.  Another is by using the `+` operator. Or by using the `string.Concat()`

string has lots of really useful methods including `Split`, `Join`, `Equals`, and `IsNullOrEmpty`/`IsNullOrWhiteSpace`

C# uses different text casing depending on where it's being declared.  Here is a summary of the conventions:

| Object          | Casing      |
| --------------- | ----------- |
| Classes         | PascalCase  |
| Public Members  | PascalCase  |
| Private Members | \_camelCase |
| Methods         | PascalCase  |
| Variables       | camelCase   |
| Enums           | PascalCase  |

### lists:&#x20;

```csharp
var list1 = new List<int>();
var list2 = new List<int> {1,2,3,4,5};
list1.Add(item:1);
list1.Remove(item:1);
list2.RemoveAt(index:3);
if list2.Contains(item:3);    
var item:int = line2.Find(match:v:int => v == 3);

```

### Dictionaries:

```csharp
var dic = new Dictionary<int, string()>;
dic.Add(0, "value1");
dic.Add(1, "value2");
dic.Add(2, "value3");

foreach(var kvp:KeyValuePair<int,string> in dic)
    Console.Writeline($"Key: {kvp.Key} contains: {kvp.Value}")
    
if (dic.TryGetValue(2, out var value:string))
    console.writeline(value);

if (dic.ContainsKey(2))
    dic[2] = "Updated Value";
```

#### hashtables:

```csharp
var table = new Hashtable
{
    {0,"value1"}
    {1,"value2"}
    {2,"value3"}
};
foreach(DictionaryEntry entry in table)
    Console.Writeline($"Entry:{entry.Key} Value: {entry.Value}");
```

### Queues:&#x20;

#### FIFO:

```csharp
var queue1 = new Queue<int>();
queue1.Enque(item:1);
queue1.Enque(item:2);
queue1.Enque(item:3);

while (queue1.TryDequeue(out var value:int))
    Console.Writeline(value);
```

#### LIFO:

```csharp
var stack2 = new Stack<int>();
stack1.Push(item:1);
stack1.Push(item:2);
stack1.Push(item:3);

while (stack1.TryPop(out var value:int))
    Console.Writeline(value);
```

### Bitwise Operators:&#x20;

```csharp
var rand = new Random();
var i1 = rand.Next(0,100);
var i2 = rand.Next(0,100); 

Console.Writeline(i1 | i2}; // OR 
Console.Writeline(i1 && i2}; // and 
Console.Writeline(i1 << i2}; // shift left 
Console.Writeline(i1 >> i2}; // shift right
Console.Writeline(i1 ^ i2}; // XOR 
```

### If / Else:&#x20;

<pre class="language-csharp"><code class="lang-csharp"><strong>var condition1 = true;
</strong><strong>var condition2 = false;
</strong><strong>var condition3 = false;
</strong><strong>
</strong><strong>if (condition1 || condition2 &#x26;&#x26; condition3) //  = true - AND statement is evaluated first, followed by the OR.
</strong>if ((condition1 || condition2) &#x26;&#x26; condition3) // = false
<strong>{
</strong>    // do something 
}

var animal = "Dog";
var sound:string = animal switch
{
    "Dog" => "Woof",
    "Cat" => "Meow",
    _ => "who knows"  // The _ => is used as a "catch all" 
}
Console.Writeline(sound) 


</code></pre>

### For Loops:

* Statement 1 is executed one time at the start of the loop.
* Statement 2 defines the condition for executing the loop code.
* Statement 3 is executed after every loop.

```csharp
for (var i = 0; i < 10; i++)
    Console.WriteLine($"i == {i}");
    
var array = new[] {1,2,3,4,5};
for (var i = 0; array.Length; i++)
    Console.WriteLine($"Array: {array[i]}");
```

### While Loop:&#x20;

```csharp
while (i < 10) 
{
    Console.WriteLine(i);
    i++
}

// ForEach Loop
var list = new List<int> {1,2,3,4,5};
foreach(var i:int in list)
    Console.WriteLine(i); 
```

#### Taking Arguments:&#x20;

```csharp
using System;
namespace Args
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            if (args.Length >= 2)
            {
                for (var i = 0; i < args.Length; i++)
                    Console.WriteLine($"Argument {i+1} is {args[i]}");
            }
            else
            {
                Console.WriteLine("Not Enough Arguments");
                ShowUsage();
                return;
            }

            void ShowUsage()
            {
                Console.WriteLine("Usage: app.exe <argv1> <argv2>");
            }
        }
    }
}
```

### Input:

```csharp
using System;
namespace ConsoleApplication1
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            void ShowUsage()
            {
                Console.WriteLine("Enter a word to echo, or enter exit to quit");
            }
            ShowUsage();
            while (true)
            {
                // create a promtp
                Console.Write("> ");    
                // read user input
                var input = Console.ReadLine();
                // if blank promt again
                if (string.IsNullOrWhiteSpace(input))
                {
                    ShowUsage();
                    continue;
                }
                else if (input.Equals("exit", StringComparison.OrdinalIgnoreCase))
                {
                    Console.WriteLine("> Now exiting");
                    break;
                }
                else
                {
                Console.WriteLine($"You Said {input}");
                }
            }
        }
    }
}
```

### Object orientation:&#x20;

```csharp
using System;
using System.Runtime.Remoting.Metadata.W3cXsd2001;

var person = new Person
{
    FirstName = "James",
    LastName = "Hammond",
};
Console.WriteLine(person.FullName);

public

internal class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName => $"{FirstName} {LastName}";
};

```
