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- First vs Single/SingleDefault - ElementAt/ElementAtOrDefault- Equality

Single

  • Both First() and Single() will return single element from the source sequence.
  • First() requires at least 1 element, that can be any element from the source squence
  • But Single()  has a special requirements for the sequence
    • If Single() call without a lambda expression as input then the sequence should have only one element 
int[] numbers = {5};

            int found = numbers.Single();
            Console.WriteLine(found);
//Output
5
    • If Single() call with a lambda expression as input then the sequence should have only one matching element for the given lambda expression
int[] numbers = {1, 2, 3};

            int found = numbers.Single(x=> x == 2);
            Console.WriteLine(found);
    • if both the cases doesn't met, Exception will be raised 

SingleOrDefault

  • Works same as FirstDefault

Element / ElementAtDefault

  • Looks for the element at a particular index
string[] names = {"Name1", "Name2", "Name3", "Name4" };

            string found = names.ElementAt(2);

            Console.WriteLine(found);
//Output
Name3
string[] names = {"Name1", "Name2", "Name3", "Name4" };

            string found = names.ElementAtOrDefault(5);
            Console.WriteLine(found);

LINQ in C# - Non-Deferred Operator Examples- (First, FirstOrDefault, Last, LastOrDefault) - Equality

First/Last - Type 1 Example 1

  • First will raise error(System.InvalidOperationException: 'Sequence contains no matching element'),  if cannot find element in the first position that is no element in the squence
string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter",
                                    "Cleveland", "Clinton", "Coolidge", "Eisenhower",
                                    "Fillmore", "Ford", "Garfield", "Grant", "Harding",
                                    "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson",
                                    "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley",
                                    "Monroe", "Nixon", "Obama", "Pierce", "Polk", "Reagan",
                                    "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren",
                                    "Washington", "Wilson" };

            Console.WriteLine(presidents.First());
//Output
Adams

First/Last - Type 2 Example 1

 Console.WriteLine(presidents.First(x=> x.StartsWith("H")));

//Output
Harding

FirstOrDefault/LastOrDefault - Example 1

  • Return first element in the sequence if not found return default value of the return type
string foundName = presidents.Take(0).FirstOrDefault();
Console.WriteLine(foundName);


string found = presidents.FirstOrDefault(x => x.Length>20);
            Console.WriteLine(found);

LINQ in C# - Non-Deferred Operator Examples- SequenceEqual - Equality

SequenceEqual

  • The SequenceEqual operator determines whether two input sequences are equal.

Type 1 - Example 1

 List<int> ItemSeq1 = new List<int> { 1, 2, 3 };
 List<int> ItemSeq2 = new List<int> { 1, 2, 3 };

            Console.WriteLine(ItemSeq1.Equals(ItemSeq2));
            Console.WriteLine(ItemSeq1.Equals(ItemSeq1));
//Output
false
true
  • How SequenceEqual it works?
  • SequenceEqual returns true 
    • If the two source sequences are of equal length and their corresponding elements are equal according to the default equality comparer for their type

Type 1 - Example 2

class Pet
{
public string Name { get; set; }
public int Age { get; set; }
}

public static void SequenceEqualEx1()
{
Pet pet1 = new Pet { Name = "Turbo", Age = 2 };
Pet pet2 = new Pet { Name = "Peanut", Age = 8 };
Pet pet3 = new Pet { Name = "Turbo", Age = 2 };
Pet pet4 = new Pet { Name = "Peanut", Age = 8 };

// Create two lists of pets.
List<Pet> pets1 = new List<Pet> { pet1, pet2 };
List<Pet> pets2 = new List<Pet> { pet1, pet2 };
List<Pet> pets3 = new List<Pet> { pet3, pet4 };
List<Pet> pets4 = new List<Pet> { pet3, pet4 };

bool Areequal1 = pets1.SequenceEqual(pets2);
bool Areequal2 = pets3.SequenceEqual(pets4);
bool Areequal3 = pets1.SequenceEqual(pets3);
bool Areequal4 = pets1.SequenceEqual(pets3);

Console.WriteLine("The lists {0} equal.", Areequal1 ? "are" : "are not");
Console.WriteLine("The lists {0} equal.", Areequal2 ? "are" : "are not");
Console.WriteLine("The lists {0} equal.", Areequal3 ? "are" : "are not");
Console.WriteLine("The lists {0} equal.", Areequal4 ? "are" : "are not");

}
 
//Output
The lists are equal.
The lists are equal.
The lists are not equal.
The lists are not equal.

Type 2 - Example 1 using IEquatable Interface

  • If you want to compare the actual data of the objects in the sequences instead of just comparing their references, you have to implement the IEquatable Interface generic interface in your class.
class Pet : IEquatable<Pet>
{
public string Name { get; set; }
public int Age { get; set; }

public bool Equals(Pet other)
{
if (other is null)
return false;

return this.Name == other.Name && this.Age == other.Age; // Compare with Values
}
}


public static void SequenceEqualEx1()
{
Pet pet1 = new Pet { Name = "Turbo", Age = 2 };
Pet pet2 = new Pet { Name = "Peanut", Age = 8 };
Pet pet3 = new Pet { Name = "Turbo", Age = 2 };
Pet pet4 = new Pet { Name = "Peanut", Age = 8 };

// Create two lists of pets.
List<Pet> pets1 = new List<Pet> { pet1, pet2 };
List<Pet> pets2 = new List<Pet> { pet1, pet2 };
List<Pet> pets3 = new List<Pet> { pet3, pet4 };
List<Pet> pets4 = new List<Pet> { pet3, pet4 };

bool Areequal1 = pets1.SequenceEqual(pets2);
bool Areequal2 = pets3.SequenceEqual(pets4);
bool Areequal3 = pets1.SequenceEqual(pets3);
bool Areequal4 = pets1.SequenceEqual(pets3);

Console.WriteLine("The lists {0} equal.", Areequal1 ? "are" : "are not");
Console.WriteLine("The lists {0} equal.", Areequal2 ? "are" : "are not");
Console.WriteLine("The lists {0} equal.", Areequal3 ? "are" : "are not");
Console.WriteLine("The lists {0} equal.", Areequal4 ? "are" : "are not");

}
 
//Output
The lists are equal.
The lists are equal.
The lists are equal.
The lists are equal.

Type 2 - Example 2 using IEqualityComparer Interface

class PetComparer : IEqualityComparer<Pet>
    {
        public bool Equals(Pet x, Pet y)
        {
            if (x is null || y is null)
                return false;

            return x.Name == y.Name && x.Age == y.Age; // Compare with Values
        }

        public int GetHashCode(Pet obj)
        {
            return obj.Name.Length; // Just for returning some integer, there is no logic used here
        }
    }
    class Pet
    {
        public string Name { get; set; }
        public int Age { get; set; }       
    }


            Pet pet1 = new Pet { Name = "Turbo", Age = 2 };
            Pet pet2 = new Pet { Name = "Peanut", Age = 8 };
            Pet pet3 = new Pet { Name = "Turbo", Age = 2 };
            Pet pet4 = new Pet { Name = "Peanut", Age = 8 };

            // Create two lists of pets.
            List<Pet> pets1 = new List<Pet> { pet1, pet2 };
            List<Pet> pets2 = new List<Pet> { pet1, pet2 };
            List<Pet> pets3 = new List<Pet> { pet3, pet4 };
            List<Pet> pets4 = new List<Pet> { pet3, pet4 };

            bool Areequal1 = pets1.SequenceEqual(pets2, new PetComparer());
            bool Areequal2 = pets3.SequenceEqual(pets4, new PetComparer());
            bool Areequal3 = pets1.SequenceEqual(pets3, new PetComparer());
            bool Areequal4 = pets1.SequenceEqual(pets3, new PetComparer());

            Console.WriteLine("The lists {0} equal.", Areequal1 ? "are" : "are not");
            Console.WriteLine("The lists {0} equal.", Areequal2 ? "are" : "are not");
            Console.WriteLine("The lists {0} equal.", Areequal3 ? "are" : "are not");
            Console.WriteLine("The lists {0} equal.", Areequal4 ? "are" : "are not");
//Output
The lists are equal.
The lists are equal.
The lists are equal.
The lists are equal.

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

Framework Fundamentals - String - Comparing Strings

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