Data Types and Variables

// Declaring variable
int x = 0;
float y = 0.0F;
bool t = false;
decimal d = 0.0M;


// Type Inference
var x = 10;               // int
var x = true;             // bool
var x = "Hassan";    	  // string


// Implicitly typed variables must be initialized with proper value
var str = null             // invalid, compiler can't figure out type of str
var str = (string) null;   // compiler can infer type of str as string, and assigned value is null


// Type Suffix
decial m = 0M;
double d = 0.0D;
float f = 0.0F;
long l = 0L;
uint uin = 0U;
ulong ul = 0UL;
More …
Primitive Types

Every programming language has its own set of basic, built-in data types using which and object oriented approach we can build more complex data types such as classes & structures. C# has its own set of basic, fundamental types. Basic built-in types in C# are stored under System namespace, they are called primitive types.

Since primitive types are used quite often, C# has a simplified way to create them. Instead of writing code like this: System.Double x = new System.Double(); to a simpler way like this: double x = 0;

All primitive types can be conditionally divided to the following types:
  • Integral types: sbyte, byte, short, ushort, int, uint, long, ulong
  • Real float-point types: float, double
  • Real type with decimal precision: decimal
  • Boolean type: bool
  • Character type: char
  • String type: string
  • Object type: object
C# Data Types Table

C Sharp Data Types Table

Everything is Object

For each primitive data type, there is a wrapper class that represents it as an object. For example, System.Int32 class wraps the int data type, and System.Double class wraps the double data type.

int x = 0
int x = new int()                     // same as int x = 0
System.Int32 x = new System.Int32();  // same as int x = 0

All primitive types besides string are derived from System.ValueType class which in its turn is derived from System.Object. It means we can call methods of System.Object on any primitive type and all primitive types are derived from System.Object that fits .NET methodology. For example, calling GetType, you may always get FCL type that corresponds to short name. Also, can typeof operator be used for getting type of the variable. Children of ValueType are automatically stored in stack when we declare them. Basing on it, they are very fast and effective.

Boxing and unboxing

The process of converting a value type to a reference type is called boxing. The inverse process - converting a reference type to a value type, is called unboxing.

int i = 123;      // i is value type 
object o = i;     // boxing 
int j = (int)o;   // unboxing

In relation to simple assignments, boxing and unboxing are computationally expensive processes. When a value type is boxed, a new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally.

Default Value

One of the benefits of OOP is value type variables are initialized (when created) by default constructor (since everything is 0bject, there is constructor). The following table shows the default values of value types returned by the default constructors. Default constructors are invoked by using the new operator, as follows:

int x = new int();

The above statement is the same as: int x = 0;

C Sharp Default Value Table

C Sharp Default Value Table

Type Suffix Table

C Sharp Type Suffix Table

Formatting and Format Specifier

// String interpolation
// C => Currency
var foo = 10;
$"amount: {foo:C}"  // amount of money is $10
$"amount: {foo:C2}" // amount of money is $10.00

// ToString()
var cost = 1632.54; 
cost.ToString("C", new System.Globalization.CultureInfo("en-US"))  // $1,632.54
cost.ToString("C", CultureInfo.CreateSpecificCulture("ja-JP")) // ¥1,632.54
// my CurrentCulture is ja-JP
cost.ToString("C", CultureInfo.CurrentCulture)  // ¥1,632.54
cost.ToString("C4", CultureInfo.CurrentCulture)  // ¥1,632.5400
Format Specifier Details


Nullable type

// Nullable types are VALUE types that can take null as value. The default value of a nullable type is null.
int? x = null;     // no value

Dynamic type

dynamic dx = 10;
dynamic dy = "quick brown fox jumped over the lazy dog";

/*
`dynamic` type is a static type, but in most cases, type 'dynamic' behaves like it has type object.
dynamic bypasses static type checking - variables of type dynamic are compiled into variables of type object.
Therefore, type dynamic exists only at compile time, not at run time
*/

Readonly and Constant

/*
Constants are accessed as if they were static fields because the value of the constant is the same for all instances of the type. 
You do not use the static keyword to declare them. 
Expressions that are not in the class that defines the constant must use the class name, a period, and the name of the constant to access the constant
*/
static class Constants
{
    public const double Pi = 3.14159; // no need to use static keyword
}
var area = Constants.Pi * (radius * radius);


// can be assigned only once (declaration time, in constructor, in static constructor)
public readonly int y = 5;

class Foo
{
    readonly int bar;
	
    Foo(int bar)
    {
        this.bar = bar;
    }
}
More …

The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be assigned multiple times in the field declaration and in any constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, while a const field is a compile-time constant, the readonly field can be used for runtime constants as in the following example:

public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;

See: readonly (C# Reference)

Type Casting

// Implicit Casting
int x = 5
long y = x;    // implicitly converted, no data is lost
Derived d = new Derived(); 
Base b = d;   // Always OK.

// Explicit Casting
double  x = 1234.56;
int y = (int) x ;    // y = 1234,  data lost by explicitly casting
Animal x = new Animal(); 
Cat y = (Cat) x;

// To avoid exception: use `is` & `as` operator
if (myObject is Foo)
{
    // casting
}
var x = "Hassan";
var y = x as object;

// Convert Class
var intString = "123"
var intVal = Convert.ToInt32(intString);

// TryParse
var intAsString = "10";
Int32.TryParse(intAsString, out intVal);

Operators

// C# standard operators => same as standard C operators

// C# special operators
x?.y    // safe navigation / conditional access
x?[]    // conditional element access
x ?? y  // Null-coalescing Operator, returns x if it is not null; otherwise, returns y

/*
default(T) : returns the default initialized value of type T, 
null for reference types, zero for numeric types, and zero/null filled in members for struct types
*/
static public T MyGenericMethod<T>(){
    T temp = default(T);
    return temp;
}

&x // address of 'x'
*x // dereferencing

/*
-> operator combines pointer dereferencing and member access
-> operator can be used only in code that is marked as unsafe
*/
x->y // is equivalent to (*x).y
More …

See: C# Operators (Arithmetic, Relational, Logical, Assignment, Precedence)

typeof
System.Type type = typeof(ref or alias);  // same as ref.GetType()`
sizeof
// returns the size in bytes of the type operand
int intSize = sizeof(int);  // Constant value = 4 (4 bytes)
is
// Checks if an object is compatible with a given type
if(obj is MyObject){ }
as
  • conversion between compatible reference types or nullable types
  • The ‘as’ operator is like a cast operation. However, if the conversion isn’t possible, ‘as’ returns null instead of raising an exception.
Overflow checking for expression
checked{
    int i3 = 2147483647 + ten;
    Console.WriteLine(i3);
}
// Checked : enables overflow checking for expression
// Unchecked : disables overflow checking for integer operations. This is the default compiler behavior
~
/*
~ performs a bitwise complement operation on its operand, which has the effect of reversing each bit
~ used for destructor
*/
var x = 110
var y = ~x  // 001
public class Person{
    public Person(){}   // ctor
    public ~Person(){}  // destructor
}
Operator precedence

Same as C operator precedence

Operator Overloading

Example: overloading ‘+’ operator to add 2 complex numbers

public struct Complex 
{
   private int real;
   private int imaginary;

   public Complex(int real, int imaginary) 
   {
      this.real = real;
      this.imaginary = imaginary;
   }
   
   public static Complex operator +(Complex c1, Complex c2) 
   {
      return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
   }
   
   public override string ToString()
   {
      return($"{real} + {imaginary}i");
   }

   public static void Main() 
   {
      Complex num1 = new Complex(2,3);
      Complex num2 = new Complex(3,4);

      Complex sum = num1 + num2;
      Console.WriteLine("The sum of the two numbers: {0}",sum);
 
   }
}

Conventions to follow:

  • operator function must be a member function of the containing type
  • operator function must be static
  • arguments of the function are the operands
  • return value of the function is the result of the operation

Tip:

The string type itself uses overloaded operators. This is how concatenation works.


Note:

+, * => may produce arithimetic overflow >> use checked block
/  => may rise DivideByZeroException

Math

var foo = 9;
var sqrtVal = Math.Sqrt(foo);
Console.WriteLine(sqrtVal);

var foo = 3;
var powVal = Math.Pow(foo, 2);
Console.WriteLine(powVal);

var foo = -15;
var absoluteVal = Math.Abs(foo);
Console.WriteLine(absoluteVal);
More …
Radian-Degree Conversion
var deg = 120;
var radians = deg * (Math.PI / 180);
Console.WriteLine(radians);

var degrees = radians * (180 / Math.PI);
degrees = Math.Round(degrees, 2);
Console.WriteLine(degrees);	
Links

Binary

// int to binary
int foo = 5;
string binary = Convert.ToString(foo, 2);
Console.WriteLine(binary);    // 101

// binary to int
var bar = Convert.ToInt32("101", 2);
Console.WriteLine(bar);    // 5

// binary with padding left
string bin = Convert.ToString(1234, 2).PadLeft(16,  '0');
Console.WriteLine(bin);  // 0000010011010010

// Convert from any classic base to any base in C#
// Supported bases are 2, 8, 10 and 16
String number = "100";
int fromBase = 16;
int toBase = 10;
String result = Convert.ToString(Convert.ToInt32(number, fromBase), toBase);

More …
Links

Control Flow - Branching

// if
if () {

} else if(){

} else {

}


// switch
switch (i) {
case 0:
    CaseZero();
    break;
	
case 1:
    CaseOne();
    break;
	
default:
    CaseOthers();
    break;
}
// case <constant or constant expressions>
// case Foo foo
// case Foo foo when foo.bar > 10

// switch expression => C# 8+
var result = bank.Status switch {
	BankBranchStatus.Open => true, 
	BankBranchStatus.Closed => false, 
	BankBranchStatus.VIPCustomersOnly => isVip
};


// Conditional or Ternary Operator
var sign = (x >= 0) ? "+ve" : "-ve";
More …

See: Switch (C# reference)

Control Flow - Looping

// for loop
for(var i = 1; i <= n; i++){

}


// foreach loop
// used to read item from IEnumerable  / IEnumerable <T>  (to manipulate items use for loop or iterator)
var items = new int[] { 1, 2, 3, 5, 8};
foreach (var item in items){

}


// while loop
while(node != null){
    // ... ... ...
    node = node.Next;
}
More …

You can use break and continue inside loop

Access Modifier

Declared accessibility Meaning
public Access is not restricted
private Access is limited to the containing type
protected containing class and derived class
internal assembly level
protected internal derived class and assembly level
default access modifier
(when no access modifier is mentioned)
fields + structure: private
methods + enum : public
for class : internal (assembly level)

Struct

public struct Coords
{
    public int x, y;

    public Coords(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}
More …
  • A struct type is a value type that is typically used to encapsulate small groups of related variables
  • It is an error to define a parameterless constructor for a struct
  • It is also an error to initialize an instance field in a struct body
  • Unlike classes, structs can be instantiated without using the new operator. In such a case, there is no constructor call, which makes the allocation more efficient. However, the fields will remain unassigned and the object cannot be used until all of the fields are initialized
  • If you instantiate a struct object using the parameterless constructor, all members are assigned according to their default values.
  • When writing a constructor with parameters for a struct, you must explicitly initialize all members; otherwise one or more members remain unassigned and the struct cannot be used, producing compiler error CS0171.
  • Structs can also contain constructors, constants, fields, methods, properties, indexers, operators, events, and nested types, although if several such members are required, you should consider making your type a class instead.
  • Structs can implement an interface but they cannot inherit from another struct. For that reason, struct members cannot be declared as protected.
  • Structs are copied on assignment. When a struct is assigned to a new variable, all the data is copied, and any modification to the new copy does not change the data for the original copy. This is important to remember when working with collections of value types such as Dictionary<string, myStruct>.
  • A struct cannot be null, and a struct variable cannot be assigned null unless the variable is declared as a nullable value type.
  • struct (C# Reference)

Class

public class Customer
{
   // Fields, properties, methods and events go here...
}
Customer customer = new Customer();


// Class inheritance
public class Manager : Employee
{
    // Employee fields, properties, methods and events are inherited
    // New Manager fields, properties, methods and events go here...
}


// Abstract Class
public abstract class A
{
    public abstract void DoWork(int i);
}
public class B : A
{
    public override void DoWork(int i)
    {
        // implementation.
    }
}


// Sealed class => can not be inherited (String is sealed class)
public sealed class D
{
    // Class members here.
}


// Partial Classes
public partial class Employee
{
    public void DoWork()
    {
    }
}

public partial class Employee
{
    public void GoToLunch()
    {
    }
}
More …
About partial class:
  • The partial keyword indicates that other parts of the class, struct, or interface can be defined in the namespace. All the parts must use the partial keyword. All the parts must be available at compile time to form the final type. All the parts must have the same accessibility, such as public, private, and so on.
  • If any part is declared abstract, then the whole type is considered abstract. If any part is declared sealed, then the whole type is considered sealed. If any part declares a base type, then the whole type inherits that class.
  • All the parts that specify a base class must agree, but parts that omit a base class still inherit the base type. Parts can specify different base interfaces, and the final type implements all the interfaces listed by all the partial declarations. Any class, struct, or interface members declared in a partial definition are available to all the other parts. The final type is the combination of all the parts at compile time.
See:

Constructor

// If you don't provide a constructor for your struct, 
// C# relies on an implicit parameterless constructor to automatically initialize each field to its default value.
public class Person {
   private string name;
   public Person(string name){
      self.name = name;
   }
   // ... ... ...
}

// expression body definition ctor
public class Location {
   public string Name { get; set; } 
   public Location(string name) => Name = name;
}


// resuing ctor: this()
public class Employee {
    public int Salary;
	
    public Employee(int annualSalary){
        Salary = annualSalary;
    }
	
    public Employee(int weeklySalary, int numberOfWeeks){
        Salary = weeklySalary * numberOfWeeks;
    }
}
public class Employee {
    public int Salary;
	
    public Employee(int annualSalary){
        Salary = annualSalary;
    }
	
    public Employee(int weeklySalary, int numberOfWeeks) : this(weeklySalary * numberOfWeeks) { }
}


// base ctor: base()
public class Manager : Employee {
    public Manager(int annualSalary) : base(annualSalary) {
        //Add further instructions here.
    }
}
More …
Static constructor
public class Adult : Person {
   private static int minimumAge;
   static Adult() {
      minimumAge = 18;
   }
}
public class Child : Person {
   private static int maximumAge;
   static Child() => maximumAge = 18;
}
Links

Properties and Fields

// Property
// following property has backing field and does data sanitization/validation
class TimePeriod {

   private double _seconds;

   public double Hours {
   
       get { return _seconds / 3600; }
	   
       set { 
            if (value < 0 || value > 24) {
                throw new ArgumentOutOfRangeException($"{nameof(value)} must be between 0 and 24.");
            }
			
            _seconds = value * 3600; 
       }
   }
}

// Expression body definitions
public class Person {
   public string Name => $"{_firstName} {_lastName}";   
}

// get and the set accessor can be implemented as expression-bodied members
public string Name {
    get => _name;
    set => _name = value;
}

// Auto-implemented properties 
// => when get and set accessors just assign a value to or retrieve a value from a backing field without including any additional logic
class Person {
    public string Name { get; set; }
    public string Foo { get; set; } = string.Empty;
}

// Restricting Accessor Accessibility
class Person {
    public string FirstName { get; private set; }          
}


// Get only accessor
class Person {
    private string _name;            // the name field
    public string Name => _name;     // the Name property            
}
public class Measurements {
    public ICollection<DataPoint> points { get; } = new List<DataPoint>();
}

// Hiding property from parent class using new keyword
public class Foo {
    public new string Name {get; set;}
}



// Field
public class Foo
{
    // private field
    private DateTime date;

    // public field (Generally not recommended.)
    public string day;
	
    private string otherDay = "";
}
More …
Property
  • for Auto-implemented properties => compiler provides backing fields
  • value is magic keyword available inside set block (same as swift newValue)
  • interface can have property
  • property can ve virtual and abstract (will be overridden by sub-class)
  • property can be readonly
  • property can be static
"Properties are logically the same as fields. A property is a named aspect of an object's state whose value is typically accessible through get and set accessors.
Properties may be read-only, in which case a set routine is not supported." - microsoft

"... properties ... act like methods to the creator of the class but look like fields to clients of the class." - Jesse Liberty
"properties, ... act like methods to the creator of the class but look like fields to clients of the class" is true for C#, but is not true in Java

property vs public fields: property prefered for encapsulation and validation
Cached evaluated properties
public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    private string fullName;
    public string FullName
    {
        get
        {
            if (fullName == null)
                fullName = $"{FirstName} {LastName}";
            return fullName;
        }
    }
}
Field vs Property

See: What is the difference between a field and a property?

An important difference is that interfaces can have properties but not fields. This, to me, underlines that properties should be used to define a class’s public interface while fields are meant to be used in the private, internal workings of a class. As a rule I rarely create public fields and similarly I rarely create non-public properties.


See

Object initializers

public class Cat {
    // Auto-implemented properties.
    public int Age { get; set; }
    public string Name { get; set; }

    public Cat() {
    }

    public Cat(string name) {
        this.Name = name;
    }
}
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = 10 };



// setting indexer in object intialiser
public class Foo {
  private var binary = new string[2];
  
  public string this[int i] {
    get { return items[i]; }
    set { items[i] = value; }
  }
}
var foo = new Foo { [0] = "zero", [1] = "one" };



// Object Initializers with anonymous types
var pet = new { Age = 10, Name = "Fluffy" };
/*
Although object initializers can be used in any context, they are especially useful in LINQ query expressions. 
Query expressions make frequent use of anonymous types, which can only be initialized by using an object initializer, 
as shown in the following declaration.
*/
var productInfos =
    from p in products
    select new { PName = p.ProductName, PPrice = p.UnitPrice };
	
foreach(var p in productInfos){
	var name = p.PName
	var price = p.PPrice
	// ...  ... ...
}
More …

Method

accessModifier returnType MethodName(type parameter){
    // .Net convention => method name starts with Capital letter
    // method signature => method name + parameters (return type does not count)
}


// Default  parameter / Optional Argument
public void GetFoo(int bar, var baz = 10){
    // Optional Arguments must be at the end
}


// Named argument
public void GetFoo(int bar, var baz = 10){
}
GetFoo(baz: 5, bar: 2)  // argument order can be different is called with name
GetFoo(2, baz: 5)  // If you mix arguments then named arguments must be at the end


// Variable parameter
public static void UseParams(bool flag, params int[] list) {
	/*
	# The params parameter must be a single dimensional array
	# params must be at the end of parameter 
	# only one params keyword is permitted in a method
	*/
}
UseParams(flag: true, 1, 2, 3, 4);


// ref
public int ExampleMethod(ref int x){ // x must be initialized

}
int val = 10;            
ExampleMethod(ref val);


// out
public int ExampleMethod(out int x){ // x does not have to be initialized
    // out parameter must be initialized here before return
}     
ExampleMethod(out val);


// Ref return
public ref double GetEstimatedDistance()
{
    return ref estDistance;
}
ref int distance = GetEstimatedDistance()  // only ref local variable can catch value returned by ref return method


// Expression body definitions
public int GetFoo(int bar) =>  bar + 10;
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public Customer this[long id] => store.LookupCustomer(id);

// calling base class methos from derived class
public Class Hassan : Person {
    public new int GetAge(){
        return base.GiveAge(); // Calling method of base class that has been hidden
    }
}
More …
Ref and Out for method signature

ref and out are not part of method signature. Therefore, methods cannot be overloaded if the only difference is that one method takes a ref argument and the other takes an out argument. following is error

public void SampleMethod(out int i) { }
public void SampleMethod(ref int i) { }
Anonymous method
public delegate int MyDelegate(int k); // declared at namespace level

// ... ... ...

MyDelegate Foo = delegate (int k) {
    return k * k;
};
var y = Foo(12)  // 144
Overriding

override : use virtual keyword in base class and override keyword in sub class

Shadowing

override and use new keyword in sub-class (hides parent class implementation)

public class Foo {
    public virtual void DoIt() {}
}

public class Bar:  Foo {
    public override new void DoIt() {}
}

Local Function

private static string GetFoo(int x) {

    var foo = GetBar() + 10
    return foo;
	 
    // Declare a local function.
    string GetBar(){
        //... ... ...
        return x / 2;   
    }
} 
More …
  • C# 7.0+
  • They can only be called from their containing member
  • Local functions can be declared in and called from:
    • Methods, especially iterator methods and async methods
    • Constructors
    • Property accessors
    • Event accessors
    • Anonymous methods
    • Lambda expressions
    • Finalizers
    • Other local functions
  • local functions can’t be declared inside an expression-bodied members
  • Local functions can use the async and unsafe modifiers.
  • all local variables that are defined in the containing member, including its method parameters, are accessible in the local function.
  • cannot include the member access modifier. Because all local functions are private, including an access modifier, such as the private keyword
  • Local functions allow your code to fail fast and allow your exception to be both thrown and observed synchronously
  • Local functions (C# Programming Guide)

Generic Method

public int Foo<T>(T bar){
   // scope of T is only within the method
}

Indexer

// Indexer is highly specialized property which allows instances of a class (or struct to) be indexed just like arrays
public int this[int index]    // Indexer declaration  
{  
    // get and set accessors  
}

// generic implementation
public class Person<T> {
	//backing store array
	private T[] arr = new T[100];
  
	public T this[int i] {
		get{ return arr[i]; }
		set {
           arr[i] = value;  
		}
	}
}
	

// Usage 1: if your class represents list(/array) of its instances => use indexer
public Class Person {

	public string Name{get; set;}
	
	private Person[] _backingStore;
	
	public Person this[int index] {
        get{ return _backingStore[index]; }
        set{
            _backingStore[index] = value;
        }
    }
}
Person person = new Person();
person[0] = new Person() { Name = "Hassan" };
person[1] = new Person() { Name = "John Skeet" };	


// Usage 2: if your class represents list(/array) of values directly related to your class => use indexer
class TempratureRecord{

    private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 65.9F, 62.1F, 59.2F, 57.5F };

    public int Length {
        get { return temps.Length; }
    }

    public float this[int index] {
        get{ return temps[index]; }
        set{
            temps[index] = value;
        }
    }
}
More …
  • Properties can be static but indexers cannot be
  • Does not support shortened syntax as like auto prop
  • Indexers can also be declared with multiple parameters and each parameter may be a different type
  • Indexers do not have to be indexed by an integer value; it is up to you how to define the specific look-up mechanism.
  • Indexers can be overloaded
  • The signature of an indexer consists of the number and types of its formal parameters. It doesn’t include the indexer type or the names of the formal parameters. If you declare more than one indexer in the same class, they must have different signatures.
  • An indexer value is not classified as a variable; therefore, you cannot pass an indexer value as a ref or out parameter.
Indexers can be declared in interface
public interface ISomeInterface{
	// Indexer declaration:
	string this[int index]{ get; set; }
}
Why to use indexers
  • Instead of a new data structure, class itself is a data structure
  • Simplified Syntax -> syntactic sugar
    var tr = new Temp();
    var firstTemp = tr[0]  // instead of: var firstTemp = foo.tempArray[0]
    
Expression Body Definitions
class SampleCollection<T> {

   private T[] arr = new T[100];
   int nextIndex = 0;

   public T this[int i] => arr[i];
   
   public void Add(T value){
      if (nextIndex >= arr.Length) {
        throw new IndexOutOfRangeException($"The collection can hold only {arr.Length} elements.");
	  }
      arr[nextIndex++] = value;
   }
}

var stringCollection = new SampleCollection<string>();
stringCollection.Add("Hello, World");
System.Console.WriteLine(stringCollection[0]);


// both the get and set accessor can be an implemented as expression-bodied members
class SampleCollection<T>
{
   // Declare an array to store the data elements.
   private T[] arr = new T[100];

   // Define the indexer to allow client code to use [] notation.
   public T this[int i]
   {
      get => arr[i]; 
      set => arr[i] = value; 
   }
}
Links

Date and time

https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings

Char

char ch = 'x';

var ch = 'j';           // char literal
var ch = '\u006A';      // 'j', unicode escape sequence, which is \u followed by the four-symbol hexadecimal representation of a character code
var ch = '\x006A';      // 'j', a hexadecimal escape sequence, which is \x followed by the hexadecimal representation of a character code.
var ch =  (char)106;    // 'j', from int value
More …
About Char
  • The char type keyword is an alias for the ` System.Char` structure type that represents a Unicode UTF-16 character
  • The default value of the char type is \0, (that is U+0000)
  • The string type represents text as a sequence of char values
Links

Char Conversion

About char conversion
  • Char is implicitly convertible to integral types: ushort, int, uint, long, and ulong.
  • It’s also implicitly convertible to the built-in floating-point numeric types: float, double, and decimal
  • It’s explicitly convertible to sbyte, byte, and short integral types
  • There are no implicit conversions from other types to the char type. However, any integral or floating-point numeric type is explicitly convertible to char
Char to String
// interpolation
char ch = 'x';
string str = $"{ch}";

// string constructor
string str = new string(new char[] { 'x' });

// ToString()
char ch = 'x';
var str = ch.ToString();

// when char is int val
var val = 120;
string str = Char.ConvertFromUtf32(val);  // x
String to Char
string str = "Hello";
char[] characters = str.ToCharArray();

// readonly indexer of string
var str = "hovermind";
var firstChar = str[0];  // h
Chat to int
var ch = 'x';
var val = (int)ch;
Console.WriteLine(val);  // 120
Int to Char
int val = 120;
char ch = Convert.ToChar(val);
Console.WriteLine(ch);  // x

String

// Empty string
var emptyText = String.Empty;  // zero-length string ""

// Literal string
var sampleText = "This is a string";

// Verbatim string: use @
var path = @"c:\test\foo.txt";  // rather than "c:\\test\\foo.txt"

// Interpolation
var x = 10;
var sampleTextByInterpolation = $"Value of x is {x}";



// Split - instance method of String class
/*
public string[] Split(separator, StringSplitOptions options)

Seperator => Char: ' ', String: " ", Char[], String[]
if Seperator is null or empty => white-space characters are assumed to be the delimiters

Enum StringSplitOptions: None/RemoveEmptyEntries            
StringSplitOptions.None : returned array will contain String.Empty ("") elements        
StringSplitOptions.RemoveEmptyEntries : returned array will not contain String.Empty ("") elements    
*/
var foo = "..."
var words = foo.Split(' ');  // seperator char
var words = foo.Split(",")   // seperator string

char[] delimiterChars = { ' ', ',', '.', '\t' };  // seperator char array
var words = foo.Split(delimiterChars);

string[] stringSeparators  = { ";", "." };          // seperator string array
var words = foo.Split(stringSeparators , StringSplitOptions.RemoveEmptyEntries);

string theString = "Some Very Large String Here";
var array = theString.Split(new [] { ' ' }, 2); // return at most 2 parts



// Join - static method of String class
/*
String.Join<T>(String, IEnumerable<T>);
String.Join<T>(String, Enumerable.Where<T>(lambda));
public static string Join (string separator, string[] value);
public static string Join (string separator, params object[] values);
public static string Join (string separator, string[] value, int startIndex, int count);

If separator is null, an empty string (String.Empty) is used instead. 
If any member of values is null, an empty string is used instead.
*/
var result = String.Join("|", 1, 2, 3);
var foo = new string[] {"bar", "baz"}
var result = String.Join("|", foo);
var result = String.Join("|", foo, 1, 2);
More …
String constructor
// Create a string from a character array
char[] chars = { 'w', 'o', 'r', 'l', 'd' };
string textFromCharArray = new string(chars);

// Create a string that consists of a character repeated 20 times.
string textWithSameCharMultipleTimes = new string('c', 20);
Empty check
String.IsNullOrEmpty(String); // static method
String.IsNullOrWhiteSpace(String); // static method
Readonly indexer
// String class has read only indexer
string str = "test";  
char x = str[2];  // x = 's'; 
Split details
var substrings = Regex.Split(input, pattern);

Regex regex = new Regex("-"); // Split on hyphens
var substrings = regex.Split("plum--pear");

/*
The Regex.Split methods are similar to the String.Split(Char[]) method, 
except that Regex.Split splits the string at a delimiter determined by a regular expression instead of a set of characters.
*/

See: Splitting String with RegEx

Join Details

String.Join Method

Substring
Substring(startIndex); // up to end
Substring(startIndex, endIndex);

String[] pairs = { "Color1=red", "Color2=green", "Color3=blue", "Title=Code Repository" };
foreach (var pair in pairs) {

    int position = pair.IndexOf("=");
    if (position < 0) {
        continue;
    }
        
    var pre = pair.Substring(0, position);
    var post = pair.Substring(position + 1);
}   

String.Substring Method

Replace
/*
public string Replace (char oldChar, char newChar);
public string Replace (string oldValue, string newValue); // If newValue is null, all occurrences of oldValue are removed.
*/
String str = "1 2 3 4 5 6 7 8 9";
var foo = str.Replace(' ', ',')  // "1,2,3,4,5,6,7,8,9"

string errString = "This docment uses 3 other docments to docment the docmentation";
string correctString = errString.Replace("docment", "document");

// static and instance methods
Regex.Replace(string[], pattern, replaceWith);  // Regex.Replace(arr, @",", String.Empty);
Regex.Replace(overloads);  
Contains
public bool Contains (string value);

String.IndexOf Method

String Conversion

Char to String
// interpolation
char ch = 'x';
string str = $"{ch}";

// string constructor
string str = new string(new char[] { 'x' });

// ToString()
char ch = 'x';
var str = ch.ToString();

// when char is int val
var val = 120;
string str = Char.ConvertFromUtf32(val);  // x
String to Char
string str = "Hello";
char[] characters = str.ToCharArray();

// readonly indexer of string
var str = "hovermind";
var firstChar = str[0];  // h
Char Array to String
// string constructor
var charArray = new char[] { 'a', 'b', 'c' };
var str = new String(charArray);
Console.WriteLine(str);

var charArray = new char[] { 'a', 'b', 'c' };
var str = String.Join(" ", charArray);
Console.WriteLine(str);  // "a b c"
String to Char Array
// string is char array
var str = "abcd";
foreach(var ch in str){
	Console.WriteLine(ch);
}

// ToCharArray()
var str = "abcd";
var chars = str.ToCharArray();
foreach(var ch in chars){
	Console.WriteLine(ch);
}

// read only indexer of string
for(var i = 0; i < str.Length; i++) {
	var ch = str[i];
	Console.WriteLine(ch);
}
Array to String
var str = String.Join(" ", new char[] { 'a', 'b', 'c' });
Console.WriteLine(str);  // "a b c"

str = String.Join(" ", 'a', 'b', 'c');
Console.WriteLine(str);  // "a b c"

str = String.Join(" ", new string[] { "hover", "mind" });
Console.WriteLine(str);  // "hover mind"

str = String.Join(" ", "hover", "mind");
Console.WriteLine(str);  // "hover mind"

str = String.Join("|", 1, 2, 3);
Console.WriteLine(str);  // "1|2|3"
String to Word Array
var words = str.Split(seperator, StringSplitOptions options)  // seperator => Char: ' ' / String: " " / Char[] / String[]
/*
if separator is null or "" => deault (white-space characters) will be used
StringSplitOptions.None => returned array contains both empty and non-empty items
StringSplitOptions.RemoveEmptyEntries => returned array contains only non-empty items
when using String[] as seperator =>  must use StringSplitOptions
*/

var str = "ab cd ef";
var words = str.Split(' ');                            // seperator: char
var words = str.Split(new char[] { ' ' });             // seperator: char array  => method signature: Split(Char[])
var words = str.Split(" ");                            // seperator: string
// string array as seperators => method signature: Split(Char[], StringSplitOptions)
var words = str.Split(new string[] { " ", "|" }, StringSplitOptions.None);   // when using string array => must use StringSplitOptions

foreach(var word in words){
	Console.WriteLine(word);
}
String to List
List<string> words = myString.Split(" ").ToList()
List to String
//String.Join(string separator,  IEnumerable<T> collection);
List<string> words = new List<string> { "hover", "mind" };
var str = String.Join(" ",  words);
Console.WriteLine(str);
Dictionary to String
string str = string.Join(";", myDict.Select(kv => kv.Key + "=" + kv.Value).ToArray());
String to Dictionary
var dict = text.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries)
               .Select(part => part.Split('='))
               .ToDictionary(split => split[0], split => split[1]);
Binary Digits as String
string binaryString = Convert.ToString(n, 2); // "110011010111"
int value = Convert.ToInt32("11001", 2)

Array

// Creating array
int[] foo = new int[10];
var foo = new int[10];            // type inferred

int[,] foo = new int[10, 5];      // multi-dimentional array
var foo = new int[10, 5];         // type inferred

var foo = Array.Empty<int>();
var my1DArray = Array.CreateInstance(typeof(int), 10);

var array = Enumerable.Repeat(String.Empty, 10).ToArray();    // Creating Array From Enumerable with same default value
var array = itemList.ToArray();                               // from any IEnumerable


// Initialization
var foo = new int[] { 1, 2 };      // dimention is inferred
int[] foo = { 1, 2 };              // dimention is inferred
var foo = new int[2] { 1, 2 };     // enforcing dimention

var arr = new int[,] { {1, 2, 3}, {4, 5} };    // dimention is inferred
int[,] arr = { {1, 2, 3}, {4, 5} };            // dimention is inferred


// Properties
arr.Length
arr.IsReadOnly 


// Array class static methods
Array.Sort(arr);
Array.BinarySearch(<overloads>)
Array.Reverse(arr);
Array.Resize(ref arr, n);
Array.Exists<T>(arr, Predicate<T>)
Array.Find(arr, Predicate<T>);
Array.ForEach<T>(arr, Action<T>)
More …
Understanding array

Array

  • array is a collection of a fixed number of values of same type & referred by a common name
  • an array is a data structure which can store multiple elements of same data type
  • specific element of an array is accessed by an index
  • array elements are stored in contiguous memory locations

Types:

  • 1-d
  • 2-d (matrix)
  • multi-d (nested array, jagged array)

    Array allocated in memory

    1d-array-allocated-in-memory

    1d-array-allocated-in-memory

2d-array-allocated-in-memory

2d-array-allocated-in-memory

Row-major order in 2d array

  • in computing, row-major order and column-major order describe methods for storing multidimensional arrays in linear memory
  • row-major order is a method of representing multi dimension array in sequential memory
  • reading memory in contiguous locations is faster than jumping around among locations. Therefore row-major is better and used by most compiler (C and C++ use row-major, Fortran and matlad uses column major)

Finding array element by row-major

offset = row * columnSize + column
Jagged array - array of arrays
// Jagged array - array of arrays
int[][] jaggedArray = new int[n][]; // 2nd diention is variable, can't be specified
var jaggedArray = new int[][]{
    new int[] {1,3,5,7,9},
    new int[] {0,2,4,6},
    new int[] {11,22}
};
Readonly array
Array.AsReadOnly(T[]) // Returns a read-only wrapper for the specified array.

var items = new int[] {1 ,2, 3, 4}
var readOnlyItems = Array.AsReadOnly(items)
Links

Array Conversion

array to string
var words = new string[] { "hover", "mind" };    // String.Join(string separator, params string[] values);
var str = String.Join(" ", words);

List<int> primes = GetPrimes(count: 20);          
var primeString = String.Join(" ", primes)      // String.Join(string separator, params object[] values);
string to array
string[] words = sentence.Split(" ");
string[] words = sentence.Split(new string[]{ " ", "," });
string[] words = sentence.Split(" ", StringSplitOptions.None);
string[] words = sentence.Split(" ", StringSplitOptions.RemoveEmptyEntries);

string[] words = sentence.Split(new char[]{ ' ' });
string[] words = sentence.Split(new char[]{ ',' }, StringSplitOptions.RemoveEmptyEntries);
string[] words = sentence.Split(",;.".ToCharArray());

var word = "hovermind"
char[] chars = word.ToCharArray()
array to list
var list = new List<T>(array);
var list = array.ToList();

var list = new List<T>();
list.AddRange(array);
list to array
string[] arr = list.ToArray();
array to dictionary
var dict = array.ToDictionary(key => key, value => value); // key == value == each item
// to avoid duplicate key, use index as key
var dictionary = array.Select((v, i) => new {Key = i, Value = v}).ToDictionary(o => o.Key, o => o.Value);
// to avoid duplicate key, use hashset
var hashset = new HashSet<string>(array);
var dict = hashset.ToDictionary(key => key, value => value);
dictionary to array
var array = dict.Values.ToArray();
var array = dict.Keys.ToArray();

T[] array = new T[dict.Count];
dict.Values.CopyTo(array, 0); // starting from 0 index
// using LINQ - has overhead (calling Lambda each time)
var array = dict.Select(pair => pair.Value).ToArray();    // CopyTo() is faster than ToArray()

List

// Creating list
List<string> cities =  new List<string>();

var cities = new List<string>();               // type inference
cities.Add("Tokyo");
cities.Add("Seoul");


// Initialization 
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
List<Cat> cats = new List<Cat> {
    new Cat{ Name = "Sylvester", Age=8 },
    new Cat{ Name = "Whiskers", Age=2 }
};


// Property
list.Count                      // FYI => array.Length


// O(1) operations
list[index]                     // indexer
list.ElementAt(index)           // slower than indexer
list.ElementAtOrDefault(index)

list.Add(T)  // at the end
list.AddRange(IEnumerable<T>)  // at the end
list.RemoveAt(Count - 1)


// O(n) operations
list.Contains(T item);
list.Sort();
list.Reverse();
list.IndexOf(T item);         // first occurrence
More …
Remove duplicate without using HashSet
var myList = new List<int>() {1, 2, 3, 4, 3, 2, 1, 5, 1};
myList = myList.Distinct().ToList();
Links

List Conversion

list to string
var combindedString = String.Join(" ", list); 
string to list
List<string> words = myString.Split(delimiters, StringSplitOptions.RemoveEmptyEntries).ToList();
// T[] delimiters, T == Char, string

List<string> words = myString.Split(" ").ToList()
list to array
string[] arr = list.ToArray();
array to list
var list = new List<T>(array); // new List<T>(IEnumerable)
var list = array.ToList();
var list = new List<T>();
list.AddRange(array);
list to dictionary
var dict = list.ToDictionary(x => x, x => x);
// to avoid duplicate key
var dict = list.Distinct().ToDictionary(x => x, x => x);
var dict = list.ToLookup(x => x);
dictionary to list
var keyList = dictionary.Keys.ToList();
var valList = dictionary.Values.ToList();

// key value pair
List<KeyValuePair<string, int>> list = dictionary.ToList();
foreach (KeyValuePair<string, int> pair in list){
  Console.WriteLine(pair.Key);
  Console.WriteLine(pair.Value);
}

// when values are nested list
Dictionary<K, List<V>> dictionary = GetDictionary();
List<List<V>> nestedList = dictionary.Values;
List<V> list = nestedList.SelectMany(item => item).ToList();
How to get duplicate items from a list using LINQ
List<String> duplicates = list.GroupBy(item => item)
                             .Where(g => g.Count() > 1)
                             .Select(g => g.Key)
                             .ToList();
Flattening nested list
List<List<V>> nestedList = GetNestedList();
List<V> list = nestedList.SelectMany(item => item).ToList();

Dictionary

// Creating dictionary
Dictionary<int, string> dict = new Dictionary<int, string>()
var dict = new Dictionary<int, string>()

// adding value
dict[0] = "foo";
dict[1] = "bar";

//reading value
var foo = dict[0]


// Initialization
var dictionary = new Dictionary<int, string>{ {1, "One"}, {2, "Two"} }
// new dictionary initializer
var dictionary = new Dictionary<int, string> {
     [1] = "One",
     [2] = "Two"
}


// Property 
dictionary.Count


// Looping
foreach(var keyValuePair in itemsDict){
  var key = keyValuePair.Key;
  var val = keyValuePair.Value;
}


// O(1) operations
dictionary.Add(key, value);    // might be O(n) too
// get
string val = dictionary[key];
if (dictionary.TryGetValue(key, var out valForKey)) {
}
// contains key 
var containsKey = dictionary.ContainsKey(key);
// remove by key
dictionary.Remove(key);
// remove all
dictionary.Clear();


// O(n) operations
// contains value
var containsValue = dictionary.ContainsValue(val);
// Iterate over keys 
foreach (var key in dictionary.Keys){
    Console.WriteLine(dictionary[key]);
}
// Iterate over values
foreach (var value in dictionary.Values) {
    Console.WriteLine(value);
}
// Iterate over dictionary
foreach (var keyValuePair in dictionary) {
    Console.WriteLine(keyValuePair.Key);
    Console.WriteLine(keyValuePair.Value);
}
More …
Find duplicates using dictionary
    var items = new int[] { 2, 3, 1, 4, 5, 1, 2, 3, 1, 1};

    var itemsDict = new Dictionary<int, int>();

    foreach(var item in items){
      if(itemsDict.ContainsKey(item)){ // found duplicate
        itemsDict[item] += 1;
      } else {
        itemsDict[item] = 1;
      }
    }

    foreach(var keyValuePair in itemsDict){
      Console.WriteLine($"item {keyValuePair.Key} appeared {keyValuePair.Value} times");
    }
Links

Dictionary Conversion

dictionary to string
var fooDict = new Dictionary<string, string> {
  [b] = "bar",
  [x] = "bax"
};
string fooStr = string.Join(";", fooDict.Select(kv => kv.Key + "=" + kv.Value).ToArray());
string to dictionary
var fooStr = "b=bar;x=bax";
var fooDict = text.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries)
               .Select(part => part.Split('='))
               .ToDictionary(split => split[0], split => split[1]);
dictionary to array
var array = dict.Values.ToArray();
var array = dict.Keys.ToArray();

T[] array = new T[dict.Count];
dict.Values.CopyTo(array, 0); // starting from 0 index

// using LINQ - has overhead (calling Lambda each time)
var array = dict.Select(pair => pair.Value).ToArray();
array to dictionary
var dict = array.ToDictionary(key => key, value => value); // key == value == each item

// to avoid duplicate key, use index as key
var dictionary = array.Select((v, i) => new {Key = i, Value = v}).ToDictionary(o => o.Key, o => o.Value);

// to avoid duplicate key, use hashset
var hashset = new HashSet<string>(array);
var dict = hashset.ToDictionary(key => key, value => value);
dictionary to list
var keyList = dictionary.Keys.ToList();
var valList = dictionary.Values.ToList();

// key value pair
List<KeyValuePair<string, int>> list = dictionary.ToList();

foreach (KeyValuePair<string, int> pair in list){
  Console.WriteLine(pair.Key);
  Console.WriteLine(pair.Value);
}

// when values are nested list
Dictionary<K, List<V>> dictionary = GetDictionary();
List<List<V>> nestedList = dictionary.Values;
List<V> list = nestedList.SelectMany(item => item).ToList();
list to dictionary
var dict = list.ToDictionary(x => x, x => x);

// to avoid duplicate key
var dict = list.Distinct().ToDictionary(x => x, x => x);  // var hashset = new HashSet<string>(list);
var dict = list.ToLookup(x => x);

HashSet

// Creating hashset
HashSet<int> evenNumbers = new HashSet<int>();
var oddNumbers = new HashSet<int>();
var foo = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

// Initialization
var fooSet = new HashSet<int>() {1, 2, 3};
// from array
var fooArray = new int[] { 1, 2, 3};
var fooSet = new HashSet<int>(fooArray);
// from list
var fooList = new List<int> { 1, 2, 3};
var fooSet = new HashSet<int>(fooList);


// Add
fooSet.Add("new item")

// Conatins: O(1)
if (fooSet.Contains("bar")) {
    fooSet.Remove("bar");
}

// Get item from hashset
var found = fooSet.TryGetValue("bar", out var bar);

// Properties
var uniqueItemCount = fooSet.Count

// Looping
foreach(var foo in fooSet) {

}
More …
About HashSet
  • The HashSet class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.
  • The HashSet class is based on the model of mathematical sets and provides high-performance set operations similar to accessing the keys of the Dictionary<TKey,TValue>
  • In simple terms, the HashSet class can be thought of as a Dictionary<TKey,TValue> collection without values
  • A HashSet’s behavior could be compared to using a Dictionary<TKey,TValue> by only adding/removing keys as values, and ignoring dictionary values themselves. You would expect keys in a dictionary not to have duplicate values, and that’s the point of the “Set” part.
  • The primary difference between LINQ set operations and HashSet operations is that LINQ set operations always return a new IEnumerable collection, whereas the HashSet equivalent methods modify the current collection.

HashSet<T> provides (Mathematical set operations):

  • UnionWith
  • IntersectWith
  • ExceptWith
  • SymmetricExceptWith
  • Overlaps
  • IsSubsetOf
  • IsProperSubsetOf
  • IsSupersetOf
  • IsProperSubsetOf
  • SetEquals
Check duplicates using hashset

  public static bool HasDuplicates(int[] inArray) => (inArray.Length != new HashSet<int>(inArray).Count);

  public static void Main()
  {
    var items = new int[] { 1, 2, 3, 4, 5, 2, 3};
    var items2 = new int[] { 1, 2, 3, 4, 5};
    
    Console.WriteLine($"has duplicate in items: {HasDuplicates(inArray: items)}");
    Console.WriteLine($"has duplicate in items2: {HasDuplicates(inArray: items2)}");
  }
Remove duplicates from array using hashset
string[] animals = { "cat", "dog", "cat", "leopard", "tiger", "cat"};
var hash = new HashSet<string>(animals);
string[] uniqueAnimals = hash.ToArray();
Remove duplicates from list using hashset
var animals = new string[] { "cat", "dog", "cat", "leopard", "tiger", "cat"};
var hash = new HashSet<string>(animals);
List<string> uniqueAnimals = hash.ToList(); // hash.ToList() is LINQ extension where new List<T>(HashSet<T>) is ctor overload

foreach(var animal in uniqueAnimals){
  Console.WriteLine(animal);
}
Find duplicates using hashset
    var items = new int[] { 1, 2, 3, 1, 4, 5, 1, 2, 3, 2, 1, 1};
    var uniqueItems = new HashSet<int>();
    var duplicateHolder = new Dictionary<int, int>();

    foreach(var item in items){
      if(uniqueItems.Contains(item)){ // found duplicate
        if(duplicateHolder.ContainsKey(item)){
          duplicateHolder[item] += 1;
        } else {
          duplicateHolder[item] = 2;
        }
      } else {
        uniqueItems.Add(item);
      }
    }

    foreach(var keyValuePair in duplicateHolder){
      Console.WriteLine($"item {keyValuePair.Key} appeared {keyValuePair.Value} times");
    }
Union
HashSet<int> evenNumbers = new HashSet<int>();
HashSet<int> oddNumbers = new HashSet<int>();
for (int i = 0; i < 5; i++){
    evenNumbers.Add(i * 2);
    oddNumbers.Add((i * 2) + 1);
}
HashSet<int> numbers = new HashSet<int>(evenNumbers);
numbers.UnionWith(oddNumbers);
Links

HashSet Conversion

Char Array to HashSet
var testStr = "axbycz".ToCharArray();     // if there are spaces, only one space will be in charSet
var charSet = new HashSet<char>(testStr);

// since string is char array, we can pass string directly to get hashset
var testStr = "axbycz";
var charSet = new HashSet<char>(testStr);    // if there are spaces, only one space will be in charSet
HashSet to Char Array
var charSet = new HashSet<char>("axbycz"); 
var charArray = charSet.ToArray();
String to HashSet
var str = "ax by cz";
var strArray = str.Split(" ");
var strSet = new HashSet<string>(strArray);
HashSet to String
var strSet = new HashSet<string>("ax by cz".Split(" "));
var str = String.Join(" ", strSet);
Array to HashSet
// HashSet<T>(IEnumerable<T> collection)
var fooArray = new int[] { 1, 2, 3};
var fooSet = new HashSet<int>(fooArray);
HashSet to Array
var fooSet = new HashSet<int>()  { 1, 2, 3};
var fooArray = new int[fooSet.Count];
fooSet.CopyTo(fooArray);

// LINQ
var fooArray = fooSet.ToArray();
List to HashSet
// HashSet<T>(IEnumerable<T> collection)
var fooList = new int[] { 1, 2, 3};
var fooSet = new HashSet<int>(fooList);
HashSet to List
var fooSet = new HashSet<int>()  { 1, 2, 3};
var fooList = new List<int>(fooSet);

// LINQ
var fooList = fooSet.ToList();

Stack

// creating stack
var items = new Stack<string>();

//  pushing
items.Push("foo");
items.Push("bar");
items.Push("bax");

// creating from array
var items = new Stack<string>(new string[] { "foo", "bar", "bax" });  

// count
var count = items.Count;   // 3

// peek
var bax = items.Peek();   // items.Count => 3

// pop
var bax = items.Pop();    //  items.Count => 2

// Contains
var doesContainFoo = items.Contains("foo");  // true

// remove all items
items.Clear();      //  items.Count => 0
More …
Links

Stack Conversion

Char Array to Stack
var chars = new char[] { 'a', 'x', 'b', 'y', 'c', 'z'};
var charStack = new Stack<char>(chars);
foreach(var ch in charStack){ // prints chars in reverse order
	Console.WriteLine(ch);
}
Stack to Char Array
var charStack = new Stack<char>( new char[] { 'a', 'x', 'b', 'y', 'c', 'z'});
var chars = charStack.ToArray();  // if you print chars, compiler will automatically call chars.ToString() and therefore will be printed as "zcybxa", but actually char[]

// CopyTo
var charStack = new Stack<char>( new char[] { 'a', 'x', 'b', 'y', 'c', 'z'});
var chars = new char[charStack.Count];
charStack.CopyTo(chars, arrayIndex: 0);
String to Stack
var str = "ax by cz";
var wordStack = new Stack<string>(str.Split(" "));
Stack to String
var wordStack = new Stack<string>(new string[]{ "ax", "by", "cz" }) ;
var str = String.Join(" ",  wordStack);
Console.WriteLine(str);
Array to Stack
var intArray = new int[] { 1, 3, 5, 7 };
var intStack = new Stack<int>(intArray) ;
foreach(var item in intStack){
	Console.WriteLine(item);
}
Stack to Array
var intSatck = new Stack<int>(new int[] { 1, 3, 5, 7 }) ;
var intArray = intSatck.ToArray();
foreach(var item in intArray){
	Console.WriteLine(item);
}
List to Stack
var list = new List<int>() { 1, 3, 5, 7};
var intStack = new Stack<int>(list) ;
foreach(var item in intStack){
	Console.WriteLine(item);
}

// poping in same order
list.Reverse();
var intStack = new Stack<int>(list) ;
foreach(var item in intStack){
	Console.WriteLine(item);
}
Stack to List
var intStack = new Stack<int>(new List<int>() { 1, 3, 5, 7}) ;
var list = new List<int>(intStack);

// LINK
var list = intStack.ToList();

Queue

// creating queue
var items = new Queue<string>();

//  enqueueing
items.Enqueue("foo");
items.Enqueue("bar");
items.Enqueue("bax");

// creating from array
var items = new Queue<string>(new string[] { "foo", "bar", "bax" });  
foreach(var item in items){
	Console.WriteLine(item);
}

// count
var count = items.Count;   // 3

// peek
var foo = items.Peek();      // items.Count => 3

// dequeue
var foo = items.Dequeue();     //  items.Count => 2

// Contains
var hasBax = items.Contains("bax");   // true

// remove all items
items.Clear();      //  items.Count => 0
More …
Links

Queue Conversion

Char Array to Queue
var chars = new char[] { 'a', 'x', 'b', 'y', 'c', 'z'};
var charQueue = new Queue<char>(chars);
foreach(var ch in charQueue){  // prints chars in order
	Console.WriteLine(ch);
}
Queue to Char Array
var charQueue = new Queue<char>( new char[] { 'a', 'x', 'b', 'y', 'c', 'z'});
var chars = charQueue.ToArray();  // if you print chars, compiler will automatically call chars.ToString() and therefore will be printed as "axbycz", but actually char[]
foreach(var ch in chars){
	Console.WriteLine(ch);
}

// CopyTo()
var charQueue = new Queue<char>( new char[] { 'a', 'x', 'b', 'y', 'c', 'z'} );
var chars = new char[charQueue.Count];
charQueue.CopyTo(chars, arrayIndex: 0);
foreach(var ch in chars){
	Console.WriteLine(ch);
}
String to Queue
var str = "ax by cz";
var wordQueue = new Queue<string>(str.Split(" "));
foreach(var word in wordQueue){
	Console.WriteLine(word);
}
Queue to String
var wordQueue = new Queue<string>(new string[]{ "ax", "by", "cz" }) ;
var str = String.Join(" ",  wordQueue);
Console.WriteLine(str);
Array to Queue
var intArray = new int[] { 1, 3, 5, 7 };
var intQueue = new Queue<int>(intArray) ;
foreach(var item in intQueue){
	Console.WriteLine(item);
}
Queue to Array
var intQueue = new Queue<int>(new int[] { 1, 3, 5, 7 }) ;
var intArray = intQueue.ToArray();
foreach(var item in intArray){
	Console.WriteLine(item);
}
List to Queue
var list = new List<int>() { 1, 3, 5, 7 };
var intQueue = new Queue<int>(list) ;
foreach(var item in intQueue){
	Console.WriteLine(item);
}
Queue to List
var intQueue = new Queue<int>(new List<int>() { 1, 3, 5, 7 }) ;
var list = new List<int>(intQueue);
foreach(var item in list){
	Console.WriteLine(item);
}

// LINK
var intQueue = new Queue<int>(new List<int>() { 1, 3, 5, 7 }) ;
var list = intQueue.ToList();
foreach(var item in list){
	Console.WriteLine(item);
}

Runtime Complexity of .NET Generic Collection

Generic Internal
Implementation
Add
/insert
Add
beyond
capacity
Queue
/Push
Dequeue
/Pop
/Peek
Remove
/RemoveAt
Item[index]
/ElementAt(index)
GetEnumerator Contains(value)
/IndexOf
/ContainsValue
/Find
List Array O(1) to add, O(n) to insert O(n) - - O(n) O(1) O(1) O(n)
LinkedList Doubly linked list O(1), before/after given node O(1) O(1) O(1) O(1), before/after given node O(n) O(1) O(n)
Stack Array O(1) O(n) O(1) O(1) - - O(1) O(n)
Queue Array O(1) O(n) O(1) O(1) - - O(1) O(n)
Dictionary Hashtable with links to another array index for collision O(1), O(n) if collision O(n) - - O(1), O(n) if collision O(1), O(n) if collision O(1) O(n)
HashSet Hashtable with links to another array index for collision O(1), O(n) if collision O(n) - - O(1), O(n) if collision O(1), O(n) if collision O(1) -
SortedDictionary Red-black tree O(log n) O(log n) - - O(log n) O(log n) O(log n) O(n)
SortedList Array O(n), O(log n) if added to end of list O(n) - - O(n) O(log n) O(1) O(n)
SortedSet Red-black tree O(log n) O(log n) - - O(log n) O(log n) O(log n) -