Showing posts with label Tutorials. Show all posts
Showing posts with label Tutorials. Show all posts

LINQ in C# - Non-Deferred Operator Examples - Aggregating

Count

Count - Type 1 Example 1

         string[] names = {"Arun", "Raja", "Ramkumar", "RaviRajan" };

                    int Count = names.Count(); // 4
        

Count - Type 2 with Condition Example 1

string[] names = {"Arun", "Raja", "Ramkumar", "RaviRajan" };

                        int Count = names.Count(x=> x.Length==4); // 2

LongCount

The LongCount operator returns the number of elements in the input sequence as a long.
string[] names = {"Arun", "Raja", "Ramkumar", "RaviRajan" };

                        long Count = names.LongCount(x=> x.Length==4); // 2

Sum

The Sum operator cannot have conditions
nt[] names = {1, 2, 3 , 4};

                        int sum= names.Sum()// 10

Min/Max

The Min/Max operator cannot have conditions

Min/Max - Type 1 - Example


                         int[] numbers = {1, 2, 3 , 4};
                        string[] names = { "Person A","Person B", "Person C", "Person D" };     

                        string minString = names.Min(); // Person A
                        Console.WriteLine(minString);
                        int minInt = numbers.Min(); // 1
                        Console.WriteLine(minInt);

Min/Max - Type 2 with Property Selector- Example

List<Customer> Customers = new List<Customer> {
                                    new Customer(){ CustomerID=1, Name="XYZ Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="ABC Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="MS Infotech", CustomerType="Retail" },
                                    new Customer(){ CustomerID=4, Name="Oracle" , CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=5, Name="IBM Hardware Limited", CustomerType="Retail" },
                                 };

                        string MinCustomerName = Customers.Min(x=> x.Name);
                        Console.WriteLine(MinCustomerName);
//Output
ABC Private Limited

Average

The Average operator returns the average of numeric values contained in the elements of the input sequence.

Average - Type 1 - Example 1

Average returns double return type
 
int[] numbers = {1, 2, 3 , 4};
                        double Avg = numbers.Average();
                        Console.WriteLine(Avg);  // 2.5

Average - Type 2 with Property Selector- Example

class Order
    {
        public int OrderID { get; set; }
        public int CustomerID { get; set; }
        public DateTime OrderDate { get; set; }
        public decimal Total { get; set; }     
    }

List<Order> Orders = new List<Order> {
                                    new Order(){ OrderID=1, OrderDate=new DateTime(2020,10,1), CustomerID=1, Total=1025.24M },
                                    new Order(){ OrderID=2, OrderDate=new DateTime(2020,4,1), CustomerID=1, Total=1000.24M },
                                    new Order(){ OrderID=3, OrderDate=new DateTime(2020,4,1), CustomerID=2, Total=1140.24M },
                                    new Order(){ OrderID=4, OrderDate=new DateTime(2020,2,1), CustomerID=2, Total=1160.24M },
                                    new Order(){ OrderID=5, OrderDate=new DateTime(2020,1,1), CustomerID=3, Total=1567.24M },
                                 };

decimal OrderAverage = Orders.Average(x=> x.Total);
                        Console.WriteLine(OrderAverage);

Aggregate

The easiest-to-understand definition of Aggregate is that it performs an operation on each element of the list taking into account the operations that have gone before.

Aggregate - Type 1 Example 1 Summing numbers

int[] numbers = {1, 2, 3 , 4};                   
                        var sum = numbers.Aggregate((a, b) => a + b); //output: 10 (1 + 2 + 3 + 4)
                        Console.WriteLine(sum);
This adds 1 and 2 to make 3. Then adds 3 (result of previous) and 3 (next element in sequence) to make 6. Then adds 6 and 4 to make 10.

Aggregate - Type 1 Example 2 create a csv from an array of strings

var chars = new[] { "a", "b", "c", "d" };
            var csv = chars.Aggregate((a, b) => a + ',' + b);
            Console.WriteLine(csv); // Output a,b,c,d

Aggregate - Type 2 Example 1 Summing numbers with a seed

int[] numbers = {1, 2, 3 , 4};                   
                        var sum = numbers.Aggregate(10, (a, b) => a + b); //output: 20 = (10 + 1 + 2 + 3 + 4)
                        Console.WriteLine(sum);

Aggregate - Type 2 Example 2 with a seed

var chars = new[] { "a", "b", "c", "d" };
            var csv = chars.Aggregate(new StringBuilder(), (a, b) => {
                if (a.Length > 0)
                    a.Append(",");
                a.Append(b);
                return a;
            });
            Console.WriteLine(csv);
//Output
a,b,c,d

LINQ in C# - Non-Deferred Operator Examples- Any/All/Contains - Quntifiers

Any

The Any operator returns true if any one element of an input sequence matches a condition.

Any - Type 1 - without condition - Example

  • Any without conditions, but a source sequence with at least with a single element. will return true
  string[] names = {"Name1", "Name2", "Name3", "Name4" };

            bool found = names.Any();

            Console.WriteLine(found);
//Output
True
  • Any without conditions, with a source sequence with zero element will return false.
string[] names = {};

            bool found = names.Any();

            Console.WriteLine(found);
 //Output
false

Any - Type 2 - with condition - Example

string[] names = {"Ramkumar", "Rajesh", "Manikandan", "Ram" };

            bool ThreeLetterNamefound = names.Any(x=> x.Length==3);
            Console.WriteLine(ThreeLetterNamefound); //True

            bool FourLetterNamefound = names.Any(x => x.Length == 4);
            Console.WriteLine(FourLetterNamefound); //False

All

The All operator returns true if every element in the input sequence matches a condition.
All needs to have at least one condition, it is mandatory 

string[] names = {"Arun", "Raja" };

            bool ThreeLetterNamefound = names.All(x=> x.Length == 4);
            Console.WriteLine(ThreeLetterNamefound); //True
 //Output
True 

Contains

The Contains operator returns true if any element in the input sequence matches the specified value.

Contains - Type 1 - Example 1

string[] names = {"Arun", "Raja", "Ramkumar", "RaviRajan" };

            bool Namefound = names.Contains("Raja");
            Console.WriteLine(Namefound); //True

Contains - Type 2 with Custom Comparer - Example 1

Implementation of IEqualityComparer, just for shown here for show how IEqualityComparer works


class StringComparer : IEqualityComparer<string>
    {
        public bool Equals(string x, string y)
        {
            //throw new NotImplementedException();
            return x.Length == y.Length;
        }

        public int GetHashCode(string obj)
        {
            //throw new NotImplementedException();
            return obj.GetHashCode();
        }
    }

 string[] names = {"Arun", "Raja", "Ramkumar", "RaviRajan" };

            bool Namefound = names.Contains("abcd", new StringComparer());
            Console.WriteLine(Namefound); //True

            bool NamefoundFalse = names.Contains("abc", new StringComparer());
            Console.WriteLine(Namefound); //False becuase there is no element with 3 letters

LINQ in C# - Non-Deferred Operator Examples - Conversion(ToArray, ToList, ToDictionary, ToLookup)

ToArray and ToList

  • The ToArray operator creates an array of type T from an input sequence of type T.
List<string> StudentNames = new List<string> { "Ram", "Raja", "Ravi"};

      //By default all the query opertors will return either IEnumerable/IQueryable
      IEnumerable<string> StudentsNameIEnumerable = StudentNames.Where(x => x.Length <= 4);

            string[] StudentsNameArray = StudentsNameIEnumerable.ToArray();
            List<string> StudentsNameList = StudentsNameIEnumerable.ToList();

ToDictionary - Type 1 - Example 1

class Customer
    {
        public int CustomerID { get; set; }
        public string CustomerType { get; set; }
        public string Name { get; set; }
    }

List<Customer> Customers = new List<Customer> {
                                    new Customer(){ CustomerID=1, Name="XYZ Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="ABC Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=3, Name="MS Infotech", CustomerType="Retail" },
                                    new Customer(){ CustomerID=4, Name="Oracle" , CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=5, Name="IBM Hardware Limited", CustomerType="Retail" },
                                 };

Dictionary<int, Customer> CustomerDictionary = Customers.ToDictionary(x => x.CustomerID);

ToDictionary - Type 2 with Custom comparer - Example 1

  • Same as like Group by Example with Custom Comparer, we can implement IEqualityComparer interface to compare the keys and for dictionary key must be unique, if not System.ArgumentException: 'An item with the same key has already been added.' exception will be thrown
class Customer
    {
        public int CustomerID { get; set; }
        public string CustomerType { get; set; }
        public string Name { get; set; }
    }

 class CustomerEqualityComparer : IEqualityComparer<int>
    {
        public bool Equals(int x, int y)
        {
            if (this.GetHashCode(x) == this.GetHashCode(y))
                return true;
            else
                return false;           
        }

        public int GetHashCode(int obj)
        {
            return obj;
        }
    }

List<Customer> Customers = new List<Customer> {
                                    new Customer(){ CustomerID=1, Name="XYZ Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="ABC Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=3, Name="MS Infotech", CustomerType="Retail" },
                                    new Customer(){ CustomerID=4, Name="Oracle" , CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=5, Name="IBM Hardware Limited", CustomerType="Retail" },
                                 };

Dictionary<int, Customer> CustomerDictionary = Customers.ToDictionary(x => x.CustomerID, new CustomerEqualityComparer() );

            foreach (var item in CustomerDictionary)
            {
                Console.WriteLine(item.Key);
                Console.WriteLine(item.Value.Name);

            }
//Output
1
XYZ Private Limited
2
ABC Private Limited
3
MS Infotech
4
Oracle
5
IBM Hardware Limited

ToDictionary - Type 3 with Custom Return Type- Example 1

  • This type is same as the first Type, with the small change that for the value type of the Dictionary, we specify a custom type
Dictionary<int, string> CustomerDictionary = Customers.ToDictionary(x => x.CustomerID, x=> x.Name);

ToDictionary - Type 4 Example 1

  • This type is a combination of Type 2 and Type 3.
Dictionary<int, string> CustomerDictionary = Customers.ToDictionary(x => x.CustomerID, x=> x.Name, new CustomerEqualityComparer());

ToLookup

  • Lookup works as a combination GroupBy and Dictionary
  • i.e. Same as like a Dictionary, it holds elements as a key,value pair, but in Dictionary each key will be with Single Value
  • But Lookup have Single key with Multiple Values, same as like a GroupBy option
  • All the 4 Types we saw above is applicable to ToLookUp duplicate Keys. 
//Type 1

List<Customer> Customers = new List<Customer> {
                                    new Customer(){ CustomerID=1, Name="XYZ Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="ABC Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="MS Infotech", CustomerType="Retail" },
                                    new Customer(){ CustomerID=4, Name="Oracle" , CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=5, Name="IBM Hardware Limited", CustomerType="Retail" },
                                 };

ILookup<int, Customer> CustomerDictionary = Customers.ToLookup(x => x.CustomerID, new CustomerEqualityComparer());
           
            foreach (var item in CustomerDictionary)
            {
                Console.WriteLine(item.Key);

                foreach (var itemdetail in item)
                {
                    Console.WriteLine(itemdetail.Name);
                }
            }
//Output
1
XYZ Private Limited
2
ABC Private Limited
MS Infotech

4
Oracle
5
IBM Hardware Limited

//Type 2

ILookup<int, string> CustomerDictionary = Customers.ToLookup(x => x.CustomerID, x => x.Name);
           
            foreach (var item in CustomerDictionary)
            {
                Console.WriteLine(item.Key);

                foreach (var itemdetail in item)
                {
                    Console.WriteLine(itemdetail); //Customer Name
                }
            }

//Type 3

ILookup<int, string> CustomerDictionary = Customers.ToLookup(x => x.CustomerID, new CustomerEqualityComparer());
           
            foreach (var item in CustomerDictionary)
            {
                Console.WriteLine(item.Key);

                foreach (var itemdetail in item)
                {
                   Console.WriteLine(itemdetail.Name);
                }
            }

//Type 4

ILookup<int, string> CustomerDictionary = Customers.ToLookup(x => x.CustomerID, x=> x.Name, new CustomerEqualityComparer());
           
            foreach (var item in CustomerDictionary)
            {
                Console.WriteLine(item.Key);

                foreach (var itemdetail in item)
                {
                    Console.WriteLine(itemdetail); //Customer Name
                }
            }

LINQ in C# - Examples - Range, Repeat, Empty - Generation

Range - Example

IEnumerable<int> ints = Enumerable.Range(1, 5);

            foreach (var item in ints)
                Console.WriteLine(item);
 //Output
1
2
3
4
5

Repeat - Example

IEnumerable<int> ints = Enumerable.Repea(7, 5);

            foreach (var item in ints)
                Console.WriteLine(item);
 //Output
7
7
7
7
7

Empty- Example

  • The Empty operator generates an empty sequence of a specified type.
IEnumerable<string> strings= Enumerable.Empty<string>();         
                Console.WriteLine(strings.count());
 //Output
0

LINQ in C# - Examples - Conversion Operators (Cast, OfType) and AsEnumerable, DefaultIfEmpty

  • The conversion operators provide a simple and convenient way of converting sequences to other collection types.

Cast

  • The Cast operator is used to cast every element of an input sequence to an output sequence of the specified type. 
  • Fundamentally, Cast() is implemented like this:
public IEnumerable<T> Cast<T>(this IEnumerable source)
{
foreach(object o in source)
yield return (T) o;
}
  • As you can see from the implementation of Cast(), first in cast every element of the sequence as object o, as object as the base type of all the types in C#, then it simply try to cast the object type to corresponding type using explicit casting (T) o, if this casting fails it will throw InvalidCastException.
  • So while casting of non-generic collection holding same type of object, then only we can use Cast() operator
  • Example 1
object[] ItemsSet1 = new object[]{ "01", "02", "03"};

            string[] AfterCasting = ItemsSet1.Cast<string>().ToArray();
           
            foreach (var item in AfterCasting)
                Console.WriteLine(item);
//Output
01
02
03
  • Example 2
 ArrayList ItemsSet1 = new ArrayList{ 4, 3, 2, 1};

            List<int> AfterCasting = ItemsSet1.Cast<int>().ToList();
           
            foreach (var item in AfterCasting)
                Console.WriteLine(item);
//Output
4
3
2
1

OfType

  • If a non-generic collection contains different types of objects and we want to extract only one type of object from the collection then we can use OfType.
  • For understanding how OfType works, refer the implementation below.
public IEnumerable<T> OfType<T>(this IEnumerable source)
{
foreach(object o in source)
if(o is T)
yield return (T) o;
}
  • Example 1
ArrayList ItemsSet1 = new ArrayList{ "Raja", 3, "Ravi", 1};

            List<int> AfterCasting = ItemsSet1.OfType<int>().ToList();
           
            foreach (var item in AfterCasting)
                Console.WriteLine(item);
//Output
3
1

AsEnumerable

  • The AsEnumerable operator simply causes its input sequence of type IEnumerable to be returned as type IEnumerable. 
  • Example - this example is using Query Expression Syntax
Northwind db = new Northwind(@"Data Source=.\SQLEXPRESS;Initial Catalog=Northwind");

var custs = from c in db.Customers
                  where c.City == "Rio de Janeiro"
                  select c;
foreach (var cust in custs)
           Console.WriteLine("{0}", cust.CompanyName);

DefaultIfEmpty

  • Refer the example below
List<string> StudentNames = new List<string> { "Ram", "Raja", "Ravi"};

            //In below statement the assumption is that, there is atleast one name with length >5
            //so the method first will return the first name with length >5
            //But there is no name, so exception will be thrown at runtime of Type System.InvalidOperationException:

            string FoundName = StudentNames.Where(x => x.Length > 5).DefaultIfEmpty().First();
            if(FoundName!=null)
                Console.WriteLine("found Name {0}", FoundName);
            else
                Console.WriteLine("No name found");
  • Fix is using DefaultIfEmpty Example 1 - returns default value of type string is null
List<string> StudentNames = new List<string> { "Ram", "Raja", "Ravi"};           

string FoundName = StudentNames.Where(x => x.Length > 5).DefaultIfEmpty().First();

            if(FoundName!=null)
                Console.WriteLine("found Name {0}", FoundName);
            else
                Console.WriteLine("No name found");

//Output
No name found
  • Fix is using DefaultIfEmpty Example 2 with Default Specified
 List<string> StudentNames = new List<string> { "Ram", "Raja", "Ravi"};
           
 string FoundName = StudentNames.Where(x => x.Length > 5).
DefaultIfEmpty("Akshara").First();
     
            Console.WriteLine("found Name {0}", FoundName);
//Output
found Name Akshara

LINQ in C# - Examples - Set Operators (Distinct, Union, Intersect)

  • The set operators are used to perform mathematical set-type operations on sequences.

Distinct - Example

string[] PersonNames = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland",
"Roosevelt","Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield",
"Grant", "Harding","Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy","Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Fillmore", "Pierce", "Polk","Reagan", "Roosevelt", "Fillmore", "Taylor", "Truman", "Tyler", "Van Buren", "Washington",
                                    "Wilson" };


            Console.WriteLine($"No of Persons with Duplicates: {PersonNames.Count()}");

            string[] NoDuplicates = PersonNames.Distinct().ToArray();

            Console.WriteLine($"No of Persons with out Duplicate: {NoDuplicates.Count()}");
//Output
No of Persons with Duplicates: 38
No of Persons with out Duplicate: 35

Union- Example

  • Union and Concat do the same, But if there is duplicate entry Union will remove it and Concat will not remove duplicate elements.
 string[] ItemsSet1 = { "Item1", "Item2", "Item3"};
            string[] ItemsSet2 = { "Item1", "Item4", "Item5" };

            IEnumerable<string> Concatenated = ItemsSet1.Concat(ItemsSet2);
            IEnumerable<string> Unioned = ItemsSet1.Union(ItemsSet2);

            Console.WriteLine($"No of Item After Concat: {Concatenated.Count()}");
            Console.WriteLine($"No of Item After Union: {Unioned.Count()}");
//Output
No of Item After Concat: 6
No of Item After Union: 5

Intersect- Example

string[] ItemsSet1 = { "Item1", "Item2", "Item3"};
            string[] ItemsSet2 = { "Item1", "Item4", "Item5" };
          
            IEnumerable<string> CommonItems = ItemsSet1.Intersect(ItemsSet2);

            Console.WriteLine($"No of Common Item Between these sets: {CommonItems.Count()}");
            foreach (var item in CommonItems)
                Console.WriteLine(item);
//Output
No of Common Item Between these sets: 1
Item1

Except- Example 

  • Minus off the second sequence elements from the first sequence
string[] ItemsSet1 = { "Item1", "Item2", "Item3"};
            string[] ItemsSet2 = { "Item1", "Item4", "Item5" };
          
            IEnumerable<string> AfterMinusing = ItemsSet1.Except(ItemsSet2);

            Console.WriteLine($"Item sets1 -(minus) Items sets2: {AfterMinusing.Count()}");
            foreach (var item in AfterMinusing)
                Console.WriteLine(item)
//Output
Item sets1 -(minus) Items sets2: 2
Item2
Item3

LINQ in C# - Examples - GroupBy - Grouping

  • The grouping operators assist with grouping elements of a sequence together by a common key.
  • GroupBy operator return a sequence of IGrouping<K, T> elements.
    • Where K - is key of field type which is used for grouping
    • Where T -  is actual object

GroupBy- Type 1 - with default comparer- Example

class Customer
    {
        public int CustomerID { get; set; }
        public string CustomerType { get; set; }
        public string Name { get; set; }
    }
class Program
    {       
        static void Main(string[] args)
        {
            List<Customer> Customers = new List<Customer> {
                                    new Customer(){ CustomerID=1, Name="XYZ Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="ABC Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=3, Name="MS Infotech", CustomerType="Retail" },
                                    new Customer(){ CustomerID=4, Name="Oracle" , CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=5, Name="IBM Hardware Limited", CustomerType="Retail" },
                                 };

         

            IEnumerable<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType);
           
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
                
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
        }                              
           
    }
//Output
Group Name:WholeSale

Customers
-------------
ID:1, Name:XYZ Private Limited
ID:2, Name:ABC Private Limited
ID:4, Name:Oracle

Group Name:Retail

Customers
-------------
ID:3, Name:MS Infotech
ID:5, Name:IBM Hardware Limited
  • As you can see from the above example GroupBy returns IGrouping<string, Customer>,in this key of type string because Customer.CustomerType is of type string and the as source type is of type Customer
  • It is not compulsory to put return type as  IEnumerable<IGrouping<string, Customer>>, it can be declared as var or can be return as a List, just for understanding I have used IEnumerable<IGrouping<string, Customer>>
List<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType).ToList();
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
  • Both(above/below) versions will return the same result as first Example
var CustomersGroup = Customers.GroupBy(x => x.CustomerType)
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();

GroupBy- Type 2 - with Custom comparer- Example

  • IEqualityComparer<T> Interface allows the implementation of customized equality comparison for collections
  • That is, you can create your own definition of equality for type T, and specify that this definition be used with a collection type that accepts the IEqualityComparer<T> generic interface.
  • Before we look into GroupBy - Type 2, we will discuss about IEqualityComparer interface and how it works
class CustomerEqualityComparer : IEqualityComparer<string>
    {
        public bool Equals(string x, string y)
        {
            if (this.GetHashCode(x) == this.GetHashCode(y))
                return true;
            else
                return false;          
        }

        public int GetHashCode(string obj)
        {
            return obj.Length; // Just any logic to generate hashcode
        }
    }
  • As you can see from above code the IEqualityComparer contains two methods GetHashCode and Equals
    •  GetHashCode- method is just a helper method, as IEqualityComparer<T> generic interface, we are passing string type here as CustomerType is of type string.
    • It is upto us to decide how the hashcode will be generator, 
    • Even without calling this method also we can 
    • Equals - method is the actual method for checking the equality, it is up to us to decide whether we are going to use the GetHashCode or not, for checking the equality.
    • Just for to show how it works I have implemented a dummy logic.

GroupBy- Type 2 - with Custom Equality comparer- Example

IEnumerable<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, new CustomerEqualityComparer());
          
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
  • Any way the result will be the same as the first type, as we didn't do any big change in the Custom Comparer class logic

GroupBy- Type 3 - Example

  • This type is same as the first Type, with the small change the return type of the GroupBy operator
  • In the Type 1 Example, we just specify the group by column, so the return type is the base type of the sequence i.e Customer by default
  • We have a option to specify the return data/type of the object as custom
  • In this example i am going to change the first type slightly and show to how to specify the custom return type.
IEnumerable<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, y => y);
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
IEnumerable<IGrouping<string, string>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, y => y.Name);
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(string CustomerName in item)
                {
                    Console.WriteLine($"Name:{CustomerName}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();

GroupBy- Type 4 - Example

  • Type 4 is nothing but a combination of both Type 2 and Type 3
IEnumerable<IGrouping<string, string>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, y => y.Name, new CustomerEqualityComparer());
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(string CustomerName in item)
                {
                    Console.WriteLine($"Name:{CustomerName}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();

LINQ in C# - Examples - Join, GroupJoin - Joining

  • The Join operator performs an INNER JOIN on two sequences based on keys extracted from each element in the sequences.
  • In this is example we are going to pull customers only who are having orders
  • So As we know while using INNER JOIN, table on left side should have matching record on right side table only will be pulled out
class Order
    {
        public int OrderID { get; set; }
        public int CustomerID { get; set; }
        public string OrderDate { get; set; }
        public decimal Total { get; set; }    
    }
    class Customer
    {
        public int CustomerID { get; set; }      
        public string Name { get; set; }
    }
class Program
    {      
        static void Main(string[] args)
        {
            List<Customer> Customers = new List<Customer> {
                                    new Customer(){ CustomerID=1, Name="XYZ Private Limited" },
                                    new Customer(){ CustomerID=2, Name="ABC Private Limited"},
                                    new Customer(){ CustomerID=3, Name="MS Infotech"},
                                    new Customer(){ CustomerID=4, Name="Oracle" },
                                    new Customer(){ CustomerID=5, Name="IBM Hardware Limited"},
                                 };

            List<Order> Orders = new List<Order> {
                                    new Order(){ OrderID=1, CustomerID=1, Total=1025.24M },
                                    new Order(){ OrderID=2, CustomerID=1, Total=1000.24M },
                                    new Order(){ OrderID=3, CustomerID=2, Total=1140.24M },
                                    new Order(){ OrderID=4, CustomerID=2, Total=1160.24M },
                                    new Order(){ OrderID=5, CustomerID=3, Total=1567.24M },
                                 };

            var CustomerOrder = Customers.Join(Orders,                                           
                                            c=> c.CustomerID,
                                            o => o.CustomerID,
                                            (c, o)=> new { c.Name, order = o }
                                         );
            foreach (var item in CustomerOrder)
            {
                Console.WriteLine($"{item.Name}\n");
               
                    Console.WriteLine("Order Details");
                    Console.WriteLine("-------------");
                    Console.WriteLine($"ID:{item.order.OrderID}, Total:{item.order.Total}");
                    Console.WriteLine();
            }
            Console.ReadLine();
        }
//Output
XYZ Private Limited

Order Details
-------------
ID:1, Total:1025.24

XYZ Private Limited

Order Details
-------------
ID:2, Total:1000.24

ABC Private Limited

Order Details
-------------
ID:3, Total:1140.24

ABC Private Limited

Order Details
-------------
ID:4, Total:1160.24

MS Infotech

Order Details
-------------
ID:5, Total:1567.24
  • The GroupJoin operator performs an LEFT JOIN on two sequences based on keys extracted from each element in the sequences, But one Exception is that, it return collection of values from the right side sequence, per matching record in the left side.
  • In this is example we are going to pull all customers regardless of they are having matching orders or not and if they have their corresponding orders pulled as a Sequence(Collection) instead of pulling a single record for each matching in the right side of the Sequence
  • i.e Single Customer => Collection of Orders they have
  • So As we know while using LEFT JOIN, table on left side either or not have matching record on right side table will return all the records
var CustomerOrder = Customers.GroupJoin(Orders,                                           
                                            c=> c.CustomerID,
                                            o => o.CustomerID,
                                            (c, o)=> new { c.Name, orders = o }
                                         );
            foreach (var item in CustomerOrder)
            {
                Console.WriteLine($"{item.Name} => Number of Orders: {item.orders.Count()}\n");
                if (item.orders.Count() > 0)
                {
                    Console.WriteLine("Order Details");
                    foreach (var details in item.orders)
                    {
                        Console.WriteLine($"ID:{details.OrderID}, Total:{details.Total}");
                    }
                }
                Console.WriteLine();
            }

            Console.ReadLine();
//Output
XYZ Private Limited => Number of Orders: 2

Order Details
-------------
ID:1, Total:1025.24
ID:2, Total:1000.24

ABC Private Limited => Number of Orders: 2

Order Details
-------------
ID:3, Total:1140.24
ID:4, Total:1160.24

MS Infotech => Number of Orders: 1

Order Details
-------------
ID:5, Total:1567.24

Oracle => Number of Orders: 0


IBM Hardware Limited => Number of Orders: 0

LINQ in C# - Examples - Reverse- Ordering

  • The reverse operator outputs a sequence of the same type as the input sequence but in the reverse order.
  • It returns void 
  • Example
class Point
    {
        public int x { get; set; }
        public int y { get; set; }       
    }
    class Program
    {      
        static void Main(string[] args)
        {
            List<Point> Points = new List<Point> {
                                    new Point(){ x=10, y=20 },
                                    new Point(){ x=-1, y=23 },
                                    new Point(){ x=-4, y=-9 },
                                    new Point(){ x=50, y=67 },
                                  
                                 };

            Points.Reverse();

            foreach  (var item in Points)
            {
                Console.WriteLine($"{item.x} {item.y}");
            }
            Console.ReadLine();
        }
    }
//Output
50 67
-4 -9
-1 23
10 20

LINQ in C# - Examples - OrderBy, OrderByDescending, ThenBy, ThenByDescending- Ordering

  • The ordering operators allow input sequences to be ordered.
  • It is important to notice that both the OrderBy and OrderByDescending operators require an input sequence of type IEnumerable<T> and return a sequence of type IOrderedEnumerable<T>.
  • In simple terms, If you need more ordering than is possible with a single call to the OrderBy or OrderByDescending operators, you should subsequently call the ThenBy or ThenByDescending operators.
  • You may chain calls to the ThenBy and ThenByDescending operators to subsequent calls to the ThenBy and ThenByDescending operators, because they accept an IOrderedEnumerable<T> as their input sequence and return an IOrderedEnumerable<T> as their output sequence.
  •   Type 1 - Example -1

class Student
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    class Course
    {
        public int courseId;
        public string courseName;
        public List<Student> students;


        public static List<Course> GetCourses()
        {
            List<Course> courses = new List<Course> {
        new Course {
            courseId = 1,
            courseName = "Course 1",
            students =  new List<Student> { new Student { FirstName = "Ravi", LastName = "Kumar" },
                                            new Student { FirstName = "Raj", LastName = "Kumar" },
                                            new Student { FirstName = "Mani", LastName = "Kannan" },}
        },
        new Course {
            courseId = 2,
            courseName = "Course 2",
            students = new List<Student> { new Student { FirstName = "John", LastName = "Peterson" },
                                            new Student { FirstName = "Michel", LastName = "Jakson" },
                                            new Student { FirstName = "Steve", LastName = "Adam" },}
        },
        new Course {
            courseId = 3,
            courseName = "Course 3",
            students = new List<Student> { new Student { FirstName = "Mani", LastName = "Raj" },
                                            new Student { FirstName = "Raguram", LastName = "Rajan" },
                                            new Student { FirstName = "Ram", LastName = "Nishanth" },}
        }
    };
            return courses;
        }
    }

    class Program
    {      
        static void Main(string[] args)
        {

            List<Course> Courses = Course.GetCourses();

            List<Student> StudentsList = Courses.SelectMany(x => x.students).OrderBy(x => x.FirstName).ThenBy(x => x.LastName).ToList();

            foreach  (var item in StudentsList)
            {
                Console.WriteLine($"{item.FirstName} {item.LastName}");
            }
            Console.ReadLine();
        }
    }

//Output
John Peterson
Mani Kannan
Mani Raj

Michel Jakson
Raguram Rajan
Raj Kumar
Ram Nishanth
Ravi Kumar
Steve Adam
  • Type 1 - Example -2

  • Change ordering and see results
List<Student> StudentsList = Courses.SelectMany(x => x.students).OrderBy(x => x.FirstName).ThenByDescending(x => x.LastName).ToList();

//Output
John Peterson
Mani Raj
Mani Kannan

Michel Jakson
Raguram Rajan
Raj Kumar
Ram Nishanth
Ravi Kumar
Steve Adam
  • Type 2 - Sorting Custom Types with IComparable<T> - Example

  • While Sorting Custom Types it is mandatory to implement IComparable interface on the target type
class Point:IComparable<Point>
    {
        public int x { get; set; }
        public int y { get; set; }

        public int CompareTo(Point other)
        {
           return this.x.CompareTo(other.x);
        }
    }
    class Program
    {      
        static void Main(string[] args)
        {

            List<Point> Points = new List<Point> {
                                    new Point(){ x=10, y=20 },
                                    new Point(){ x=-1, y=23 },
                                    new Point(){ x=-4, y=-9 },
                                    new Point(){ x=50, y=67 },
                                  
                                 };

            Points = Points.OrderBy(x => x).ToList();


            foreach  (var item in Points)
            {
                Console.WriteLine($"{item.x} {item.y}");
            }
            Console.ReadLine();
        }
    }

//Output
-4 -9
-1 23
10 20
50 67
  • Type 3 - Sorting Custom Types with Custom IComparer class- Example

  • While Sorting Custom Types using Custom IComparer class it not is mandatory to implement IComparable interface on the target type
class PointComparer : IComparer<Point>
    {
        public int Compare(Point p1, Point p2)
        {
            return p1.x.CompareTo(p2.x);
        }
    }

    class Point
    {
        public int x { get; set; }
        public int y { get; set; }       
    }
    class Program
    {      
        static void Main(string[] args)
        {

            List<Point> Points = new List<Point> {
                                    new Point(){ x=10, y=20 },
                                    new Point(){ x=-1, y=23 },
                                    new Point(){ x=-4, y=-9 },
                                    new Point(){ x=50, y=67 },
                                  
                                 };

            Points = Points.OrderBy((x => x), new PointComparer()).ToList();


            foreach  (var item in Points)
            {
                Console.WriteLine($"{item.x} {item.y}");
            }
            Console.ReadLine();
        }
    }

//Output
-4 -9
-1 23
10 20
50 67

Framework Fundamentals - String - Comparing Strings

In comparing two values, the .NET Framework differentiates the concepts of equality comparison and order comparison . Equality compariso...