Skip to content

Anil1111/CollectionsLambdaLinq

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Collections

  1. IEnumerator<T>, IEnumerable<T>

1.1 IEnumerator<T>

  • The IEnumerator<T> interface has properties and methods for enumerating a collection of T elements.

  • Properties:

    //Returns the element at the current position in the collection
    T Current { get; }
  • Methods:

    //Advances the current position to the next element. Returns "true" if the
    //position was advanced, "false" if there is no next element.
    bool MoveNext()
    //Sets the enumerator position to -1 (initial position)
    void Reset()
  • Any changes made to the collection while it is enumerated invalidate the current enumerator and cause an exception to be thrown when calling MoveNext or Reset.

  • More info: IEnumerator<T>

1.2 IEnumerable<T>###

  • Exposes an enumerator to iterate over a collection of T.

  • Collections that implement IEnumerable can be enumerated by using the foreach statement.

  • Methods:

    //Returns the enumerator for iterating the list
    IEnumerator<T> GetEnumerator()
  • More info: IEnumerable<T>

  1. Yield

  • Used inside a method or a get statement.

  • Allows returning an iterator (which can be iterated step by step) without the need for an additional class to handle the enumeration.

  • Syntax:

    yield return valueToReturn;
  • When execution reaches an yield statement, the current value of the iterator is returned, and the iterator state is memorized. When the method is called again, the next element is returned.

  • Iterators can be iterated using a foreach loop.

  • More info: yield, iterators

  1. Collection<T>

  • Base class for generic collections.
  • Main use: Does not have a lot of implemented functionalities, but offers possibilities for customization via overriding basic methods in subclasses.
  • Items can be accessed using the built-in indexer.
  • More info, properties and methods: Collection<T>
  1. List<T>

  • Provides methods to search, sort, and manipulate lists.
  • Items can be accessed using the indexer.
  • Main use: Not suitable for customizing and extending; but performs better than most generic collections and contains a lot of build-in functionalities such as search, sort and list operations.
  • Can be sorted using a custom Comparer<T>, or without one, if the items implement IComparable
  • More info, properties and methods: List<T>
  1. Dictionary<TKey, TValue>

  • A collection of unique keys and values corresponding to those keys.

  • Each element in the Dictionary is a KeyValuePair<TKey, TValue> struct.

  • Values can be retrieved using the keys, similarly to using an indexer. Example:

    var valueToGet = dictionary[key];
  • Main use: Storing values that need to be retrieved quickly based on a key. Retrieving a value using the key is very fast, because the Dictionary is implemented as a hash table (search speed depends on the hashing algorithm of the TKey type).

  • Key and value lists can be iterated through independently, each list being a generic IEnumerable.

  • Adding an existing key, or trying to retrieve the value of a key that is not present in the Dictionary will result in an Exception being thrown.

  • More info, properties and methods: Dictionary<TKey, TValue>

Collections - Extra (for home)

  1. Add an indexer to the BandsEnumerable class and print the items using the index.
  2. Implement the IComparable interface in the Band class. Sort a List<Band>, so you get the same result as when using the BasicBandsComparer, but without using a Comparer (you will make use of the parameterless Sort() method of the list).
  3. Any leftover //TODOs from the project.

Lambda Expressions, Delegates and Anonymous Functions

1. Delegates

What is a Delegate?

  • A delegate is a type which holds the method(s) reference in an object.
  • A delegate is a type that represents references to methods with a particular parameter list and return type.
  • A type safe function pointer. (similar with C/C++ function pointers, but type safe)

Syntax

public delegate double PerformCalculation(double x, double y);

When do you use a delegate?

  • Delegates are used to pass methods as arguments to other methods.
  • You can use it as a callback to an event.

How do you create it?

  • In order to create a delegate you can associate its instance with any method with a compatible signature and return type.

Advantages

  • Encapsulating the method's call from caller
  • Used to call a method asynchronously
  • Dynamic binding

Example

public delegate double PerformCalculation(double val1, double val2);
class DelegateExample
{
  static double fn_Sum(double val1, double val2)
  {
      return val1 + val2;
  }

  static double fn_Product(double val1, double val2)
  {
      return val1 * val2;
  }

  static void ExecuteFunction(PerformCalculation function, double param1, double param2)
  {
      double result = function(param1, param2);
      Console.WriteLine(result);
  }

  static void Main(string[] args)
  {
      // Create Delegate instances
      PerformCalculation sum_Function = new PerformCalculation(fn_Sum);
      PerformCalculation prod_Function = new PerformCalculation(fn_Product);

      double val1 = 2.0, val2 = 3.0;

      //Call sum function
      double sum_result = sum_Function(val1, val2);
      Console.WriteLine("{0} + {1} = {2}", val1, val2, sum_result);

      //Call product function
      double prod_result = prod_Function(val1, val2);
      Console.WriteLine("{0} * {1} = {2}", val1, val2, prod_result);

      //Using sum_function reference
      Console.Write("{0} + {1} = ", val1, val2);
      ExecuteFunction(sum_Function, val1, val2);

      //Using product_function reference
      Console.Write("{0} * {1} = ", val1, val2);
      ExecuteFunction(prod_Function, val1, val2);
  }
}

More info: Delegates


1.2 Func Delegates

  • Encapsulates a method that has N parameters (N from [0, 16]) and returns a value of a specific type

Syntax

/**
 * Syntax of a Func delegate which has two parameters
 * @in T1 : type of the first parameter
 * @in T2: type of the second parameter
 * @out TResult: type of the return value of the method
 */

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

Advantage

  • You don't have to declare the signature of the delegate.
  • There is no need to explicitly create a Func delegate instance (you can just pass the method name, and the compiler will bind it dynamically).

Example

class FuncDelegateExample
{
    static double fn_Sum(double val1, double val2)
    {
        return val1 + val2;
    }

    static double fn_Product(double val1, double val2)
    {
        return val1 * val2;
    }

    static double fn_Diff(double val1, double val2)
    {
        return val1 - val2;
    }

    static void ExecuteFunctionUsingFunc(Func<double, double, double> function, double param1, double param2)
    {
        double result = function(param1, param2);
        Console.WriteLine(result);
    }

    static void Main(string[] args)
    {
        //Create Func Delegate instances
        Func<double, double, double> sum_Function = new Func<double, double, double>(fn_Sum);
        Func<double, double, double> prod_Function = new Func<double, double, double>(fn_Product);

        double val1 = 2.0, val2 = 3.0;

        //Call sum function
        double sum_result = sum_Function(val1, val2);
        Console.WriteLine("{0} + {1} = {2}", val1, val2, sum_result);

        //Call product function
        double prod_result = prod_Function(val1, val2);
        Console.WriteLine("{0} * {1} = {2}", val1, val2, prod_result);

        //Using sum_function reference
        Console.Write("{0} + {1} = ", val1, val2);
        ExecuteFunctionUsingFunc(sum_Function, val1, val2);

        //Using product_function reference
        Console.Write("{0} * {1} = ", val1, val2);
        ExecuteFunctionUsingFunc(prod_Function, val1, val2);

        //Omitting the explicit creation of Func instance
        Console.Write("{0} - {1} = ", val1, val2);
        ExecuteFunctionUsingFunc(fn_Diff, val1, val2);
    }
}

More info: Func Delegate


1.3 Action Delegates

  • Similar with Func delegate but it does not return a value.

Syntax

/**
 * Syntax of a Action delegate which has two parameters
 * @in T1 : type of the first parameter
 * @in T2: type of the second parameter
 */

public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);

More info: Action Delegate


2. Anonymous functions

  • Anonymous methods let you declare a method body without giving it a name.
  • Can be used to pass a code block as a delegate parameter.
  • Cannot be called explicitly.
  • Anonymous methods enable you to omit the parameter list.

Syntax

delegate(in T1, in T2)
{
  //code block
}

Usage

Function<double, double, double> maxFunction = delegate(double var1, double var2)
                                              {
                                                if (var1 > var2)
                                                  return var1;
                                                else
                                                  return var2;
                                              }

Advantage

  • Reduce the coding overhead in instantiating delegates (you don't have to create a separate method).
  • Are more flexible than lambda expressions.

Example

public delegate double PerformCalculation(double val1, double val2);
class AnonymousExample
{
    static void ExecuteFunctionUsingFunc(Func<double, double, double> function, double param1, double param2)
    {
        double result = function(param1, param2);
        Console.WriteLine(result);
    }

    static void ExecuteFunction(PerformCalculation function, double param1, double param2)
    {
        double result = function(param1, param2);
        Console.WriteLine(result);
    }

    static void Main(string[] args)
        //Create a Func Delegate instance
        Func<double, double, double> sum_Function = delegate(double var1, double var2)
                                                    {
                                                      return var1 + var2;
                                                    };

        //Create a Delegate instance
        PerformCalculation prod_Function = delegate(double var1, double var2)
                                            {
                                                return var1 * var2;
                                            };

        double val1 = 1.0, val2 = 5.0;

        //Call sum function
        double sum_result = sum_Function(val1, val2);
        Console.WriteLine("{0} + {1} = {2}"", val1, val2, sum_result);

        //Call product function
        double prod_result = prod_Function(val1, val2);
        Console.WriteLine("{0} * {1} = {2}"", val1, val2, prod_result);

        //Using sum_function reference
        Console.Write("{0} + {1} = "", val1, val2);
        ExecuteFunctionUsingFunc(sum_Function, val1, val2);

        //Using product_function reference
        Console.Write("{0} * {1} = "", val1, val2);
        ExecuteFunction(prod_Function, val1, val2);
    }
}

3. Lambda expressions

  • A lambda expression is an anonymous function which can be used to create delegates or expression tree types.
  • Can be used to pass local functions as arguments or pass them as value of a function calls.
  • They are usually used for writing LINQ query expressions.

Syntax

(input parameters) => execution code
  • Left hand side represents zero or more parameters
  • The right hand side represents the statement body

Usage

/**
 * Input : x and y
 * Expression: x == y
 * Usage: tests if two variables are equal.
 */
(x, y) => x == y

Advantage

  • It allows you to write a method in the same place you are going to use it.
  • No need to specify the name of the function, its return type, and its access modifier.
  • It especially useful in places where a method is being used only once, and the method definition is short.
  • When reading the code you don't need to look elsewhere for the method's definition.

Differences between Lambda expressions and Anonymous methods

  • Lambda expressions doesn't use delegate keyword
  • An anonymous method explicitly requires you to define the parameter types and the return type for a method
//Anonymous method
Func<double, double, double> anonymousSum = delegate(double x, double y)
                                            {
                                              return x + y;
                                            };
//Lambda expression
Func<double, double, double> lambdaSum = (x, y) => x + y;

Example

public delegate double PerformCalculation(double val1, double val2);
class LambdaExample
{
  static void ExecuteFunctionUsingFunc(Func<double, double, double> function, double param1, double param2)
  {
      double result = function(param1, param2);
      Console.WriteLine(result);
  }

  static void ExecuteFunction(PerformCalculation function, double param1, double param2)
  {
      double result = function(param1, param2);
      Console.WriteLine(result);
  }

  public static void main(String args[])
  {
    //Use lamba expression to create a Func delegate instance
    Func<double, double, double> sum_Function = (double var1, double var2) => var1 + var2;

    //Use lambda expression without data type to create a Func delegate instance
    Func<double, double, double> sum_Function_withoutType = (var1, var2) => var1 + var2;

    //Use lamba expression to create a delegate instance
    PerformCalculation prod_Function = (double var1, double var2) => var1 * var2;

    //Use lamba expression without data type to create a delegate instance
    PerformCalculation prod_Function_withoutType = (var1, var2) => var1 * var2;

    double val1 = 4.0, val2 = 3.0;

    //Call sum function
    double sum_Result = sum_Function(val1, val2);
    Console.WriteLine("{0} + {1} = {2}", val1, val2, sum_Result);

    //Call product function
    double prod_Result = prod_Function(val1, val2);
    Console.WriteLine("{0} * {1} = {2}", val1, val2, prod_Result);

    //Using sum_function reference
    Console.Write("{0} + {1} = ", val1, val2);
    ExecuteFunctionUsingFunc(sum_Function, val1, val2);

    //Using product_function reference
    Console.Write("{0} * {1} = ", val1, val2);
    ExecuteFunction(prod_Function, val1, val2);

    //Omitting the explicit creation of a Func instance
    Console.Write("{0} - {1} = ", val1, val2);
    ExecuteFunctionUsingFunc((var1, var2) => var1 - var2, val1, val2);

    //Omitting the explicit creation of a delegate instance
    Console.Write("{0} - {1} = ", val1, val2);
    ExecuteFunction((var1, var2) => var1 - var2, val1, val2);
  }
}

4.Closure

  • A lambda expression is called closure when it captures variables from the outer scope.

Example 1

//Read example
int factor = 4;
Func<int, int> scaleWithFactor = x => x * factor;
int result = scaleWithFactor(5); //20
factor = 10;
int result2 = scaleWithFactor(10); //100

Example 2

//Modify example
int counter = 10;
Action resetCounter = () =>
                      {
      		            counter = 0;
      	             };
//counter = 10
resetCounter();
//counter = 0

Example 3

static void Main(string[] args)
{
    var inc = GetIncFunc();
    Console.WriteLine(inc(2));
    Console.WriteLine(inc(4));
    Console.WriteLine(GetIncFunc(5));
}

public static Func<int,int> GetIncFunc()
{
    var incrementedValue = 0;
    Func<int, int> inc = delegate(int var1)
                            {
                                incrementedValue = incrementedValue + 1;
                                return var1 + incrementedValue;
                            };
    return inc;
}

Linq

Stands for Language-Integrated Query, and allows traversal, filter, and projection operations over IEnumerable collections. All methods are extensions on the Enumerable class and require the System.Linq namespace.

Syntax: offers 2 alternatives:

  1. Query syntax (SQL syntax). EX:
from number in numbersList
where number % 2 == 0
select number;
  • Pro: easier to read and understand.
  • Con: not as powerful as Lambda syntax, some operations cannot be written in SQL syntax.
  1. Method syntax (Lambda syntax). EX:
numbersList.Where(number => number % 2 == 0);
  • Pro: more powerful and compact.
  • Con: harder to learn and follow.

1. Where

  • Allows filtering of the collection based on the predicate (condition).
  • The predicate is a Func that takes the type of the objects in the collection as input, and returns a bool.
  • The result of the Where operation is always an IEnumerable<T> where T is the object type in the original list.

2. Select

  • Projects the elements in the collection into another form, based on the selector.
  • The selector is a Func that takes one element from the collection and returns the new type of object.
  • The result of the Select operation is always an IEnumerable<T> where T is the type resulting from the projection.

3. Select Many

  • Flattens multi-dimensional collections, without the need for a second "select", based on the selector.
  • The selector is a Func that returns an IEnumerable<T> corresponding to one element from the original list. All the resulting IEnumerable<T> are flattened into one final IEnumerable<T> that is returned by the SelectMany method.

4. Aggregate

  • Applies a function to each element of the collection, updating an accumulator value for each execution of the function.
  • The first parameter of aggregate is the seed used for the accumulator value.
  • The accumulator function takes the accumulator value and the current iteration value, and returns the applied function result.

5. Group by

  • Groups the elements of the collection according to one of their properties (the key), using a selector.
  • The key selector Func extracts the key for each element and places the element, in order to determine the group for that element.
  • The GroupBy method result is a IEnumerable<IGrouping<T1, T2>>, where T1 is the key and T2 is the type of elements in groups.
  • IGrouping<T1, T2> is a structure similar to an IEnumerable<T2>, with an added Key property of type T1.

6. Sum, Min, Max

  • All these are methods based on Aggregate that return a value calculated by applying a transform on each element in the list.

More info: Linq Introduction, Query Operators.

Linq - Extra (for home)

  • Follow examples to implement "OrderByMethod" and "ContainsMethod" classes, similar to the other classes in the project. Provide examples of classic, Sql and Lambda implementations of the same functions.

About

Collections, Lambda, Linq

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%