Converting an image to and from a byte array

This method to convert from an image to a byte array uses the System.Drawing.Image.Save method to save the image to a memorystream. The memorystream can then be used to return a byte array using the ToArray() method in the MemoryStream class.

public byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
 MemoryStream ms = new MemoryStream();
 imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
 return  ms.ToArray();
}

This byte array to image method uses the Image.FromStream method in the Image class to create a method from a memorystream which has been created using a byte array. The image thus created is returned in this method.

public Image ByteArrayToImage(byte[] byteArrayIn)
{
     MemoryStream ms = new MemoryStream(byteArrayIn);
     Image returnImage = Image.FromStream(ms);
     return returnImage;
}

Using Enumerable.Intersect to find items in two lists

On a recent post where I discussed using LINQ to find all items in one list which also exist in another list (intersection) using linq expressions, a comment was posted suggesting I look into using Enumerable.Intersection.  So this is it.

First of all a straight forward example, finding the intersect of two lists of integers

Console.WriteLine("Number intersect...");
var lista = new List<int> { 1, 44, 56, 87, 23 };
var listb = new List<int> { 20, 23, 1 };
var numbers = lista.Intersect<int>(listb);
numbers.ToList().ForEach(i => Console.WriteLine(i));

The result of the Intersect() method returns two integers because they exist in both lists.

1
23

And a simple example using strings.

Console.WriteLine("String intersect...");
var listx = new List<string> { "Ben", "Phil", "Mary", "Paula", "Peter", "Samuel" };
var listy = new List<string> { "samuel", "Paula", "Ben" };
var names = listx.Intersect<string>(listy, StringComparer.OrdinalIgnoreCase);
names.ToList().ForEach(n => Console.WriteLine(n));

As StringComparer.OrdinalIgnoreCase is being passed as the second parameter to the Intersect() method three matches are being found, if case was not ignored the ‘samuel’ string in listy would not be included in the results.

Ben
Paula
Samuel

In the next examples I will be using a product class and two lists of products. Notice how productA and productB are declared and instantiated outside of the array initialisations.

public class Product
{
    public string Code { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
}
.
...
.
var productA = new Product { Code = "CD5", Name = "Paint", Category = "Decorating" };
var productB = new Product { Code = "FG9", Name = "Ladder", Category = "Access" };
Product[] listm = {new Product{Code="AM1",Name="Bucket", Category="Decorating"},
                    new Product{Code="AM3",Name="Brush", Category="Decorating"},
                    productA,
                    productB,
                    new Product{Code="MN4",Name="Table", Category="Furniture"}
                    };
Product[] listn = {new Product{Code="CV6",Name="Brush", Category="Decorating"},
                    productA,
                    productB,
                    new Product{Code="Am3",Name="Brush", Category="Decorating"},
                    };

Calling the Intersect method on lists of objects in this way will only return those objects that are the same instances.

Console.WriteLine("object intersect...");
Console.WriteLine("IEnuerable.Intersect<TSource>...");
var products = listm.Intersect(listn);
products.ToList().ForEach(p => Console.WriteLine(p.Code));

So by default, the results only include the two pre-instantiated objects because, as well as being in both lists, they are the same instance.

CD5
FG9

There are two more scenarios I have been considering:
1. Get a list of all product codes in both lists.
2. Get a list of all product objects where the product code is in both lists.

I initially solved the first scenario in the following way. Note how the Select() method is used to retrieve the product codes so the Intersect() method is comparing two lists of string rather than objects. also note the use of the StringComparer to ignore text case.

var codesLINQ = listm.Select(a => a.Code).Intersect(listn.Select(b => b.Code), StringComparer.OrdinalIgnoreCase);
codesLINQ.ToList().ForEach(p => Console.WriteLine(p));

As we are comparing two lists of strings, the output includes the AM3 product code because it exists in both lists even though it is not the same object instance and we are ignoring case.

AM3
CD5
FG9

The second scenario was solved using a Where() method to retrieve the objects from listm that match the product code in listn. Note again this is ignoring case.

var productsLINQ = listm.Where(a => listn.Any(b => string.Compare(b.Code, a.Code, true) == 0));
productsLINQ.ToList().ForEach(p => Console.WriteLine(p.Code));

The output to the console for this example will be the same as the previous example, the only difference is that the productsLINQ variable contains the product objects not just the product codes.

In these two scenarios LINQ has been used in some form but it is possible to get the desired results without LINQ. As these two scenarios above are so similar their solution is similar too, so I am going to focus on solving the second one without using LINQ. To solve this problem we could change the product class could implement the IEquatable generic interface or to implement the IEqualityComparer generic interface in a helper class. The advantage of the latter is that your product class better follows the Single Responsibility Principle in that it will only need to change if your product info changes, not if the comparison criteria changes. For additional information check the MSDN documentation here. Firstly the IEquatable implementation.

public class Product : IEquatable<Product>
{
    public string Code { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }

    public bool Equals(Product other)
    {
        //Check whether the compared object is null.
        if (Object.ReferenceEquals(other, null)) return false;

        //Check whether the compared object references the same data.
        if (Object.ReferenceEquals(this, other)) return true;

        //Check whether the products' properties are equal.
		return string.Compare(Code, other.Code, true) == 0;

		// alternative comparison code.
		//return Code.ToUpper().Equals(other.Code.ToUpper());
    }

    // If Equals() returns true for a pair of objects
    // then GetHashCode() must return the same value for these objects.

    public override int GetHashCode()
    {
        //Get hash code for the Code field.
        int hashProductCode = Code.ToUpper().GetHashCode();

        //Calculate the hash code for the product code.
        return hashProductCode;
    }
}

By implementing the IEquatable interface we can now control how the objects are compared. This implementation only compares the product code.
Calling the Intersect() method does not change from earlier.

var products = listm.Intersect(listn);
products.ToList().ForEach(p => Console.WriteLine(p.Code));

The products variable holds the product objects that match the comparison code. In the earlier example when the Intersect() method was called before the IEquatable interface was implemented we got two product in the result. Now with the interface implemented there are three product products in the match.

AM3
CD5
FG9

The next example (the better example IMHO) shows how to implement the IEqualityComparer interface in a ProductComparer class.
Notice how the Code and Name properties are being compared to identify a match.

public class Product
{
    public string Code { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
}

public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product x, Product y)
    {
        //Check whether the objects are the same object.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether the products' properties are equal.
        return x != null && y != null
            && x.Code.ToUpper().Equals(y.Code.ToUpper())
            && x.Name.ToUpper().Equals(y.Name.ToUpper());

		// Alternative comparison code
		/*return x != null && y != null
            && string.Compare(x.Code, y.Code, true) == 0
            && string.Compare(x.Name, y.Name, true) == 0;*/
    }

    public int GetHashCode(Product obj)
    {
        //Get hash code for the Name field if it is not null.
        int hashProductName = obj.Name == null ? 0 : obj.Name.ToUpper().GetHashCode();

        //Get hash code for the Code field.
        int hashProductCode = obj.Code.ToUpper().GetHashCode();

        //Calculate the hash code for the product.
        return hashProductName ^ hashProductCode;
    }
}

When calling the Intersect() method you pass an instance of the ProductComparer as a parameter.

var products = listm.Intersect(listn, new ProductComparer());
products.ToList().ForEach(p => Console.WriteLine(p.Code));

As well as single responsibility, another advantage to implementing the IEqualityComparer interface over the IEquatable interface is you could have multiple ProductComparer classes with different criteria e.g. one that compares the product code and one that compares the code and Name properties. You decide which one you pass to the Intersect() method.

Find all items in list which exist in another list using linq

I just wanted to go through a few examples of how to retrieve all the items in a list, that also exist in another list. This is one of those useful techniques which you may not need very often and so this post will act as a reminder.

To start with we need arrays.

var lista = new List<string>(){"one","two","three","four","five","six","seven"};
var listb = new List<string>(){"One","fortyfour","six"};

These examples are designed on the principle that we want to retrieve all the values from lista which also exist in listb. This can be done by using an explicit linq join,

result = from a in lista
    join b in listb on a.ToLower() equals b.ToLower()
    select a;

Although it could be written on a single line, this type of query is usually written over multiple lines for clarity. The same result could be achieved as below

result = lista.Where(a => listb.Any(b => a.ToLower() == b.ToLower()));

One method is not necessarily better than the other and I am sure there are a number of other ways the same result could be achieved.
I find using the string.Compare() method saves from having to keep converting to lower case.

var result = lista.Where(a => listb.Any(b => string.Compare(a,b,true) == 0));

If you were to output the contents of the result variable from both the above examples you would see they all produce the same result (based on the original array contents)

one
six

The last example will retrieve all the items from lista where the text of the item is contained in the text of an item in listb.

var result = lista.Where(a => listb.Any(b => b.Contains(a)));

Note that the Contains method is case sensitive so the result would be

four
six

because listb has an item that contains the text ‘four’, which is the text of an item in lista. Also both lists have an item with the same text ‘six’.

Arrays in VB.NET

I recently wrote a post on declaring arrays in C# and decided to convert it to VB. Below is code for a console app that demonstrates declaring Single Dimension Arrays, Multi Dimension Arrays and Arrays in Arrays, also known as Ragged or Jagged Arrays.

Module Module1

    Sub Main()
        'single dimension
        Dim ages(4) As Integer
        ages(0) = 3
        ages(1) = 6
        ages(2) = 20
        ages(3) = 34
        ages(4) = 67

        Console.WriteLine("Single Dimensional Array")
        For ageLoop = 0 To ages.Length - 1
            Console.WriteLine(String.Format("Item {0}: {1}", ageLoop, ages(ageLoop)))
        Next

        Console.Write(vbCrLf & vbCrLf & "Multi Dimensional Array" & vbCrLf)

        'multi dimensional
        Dim names(1, 1) As String
        names(0, 0) = "Andrew"
        names(0, 1) = "Bobby"
        names(1, 0) = "Susan"
        names(1, 1) = "Peter"

        Console.WriteLine("Row" + vbTab + "Col" + vbTab + "Value")
        For row = 0 To names.GetUpperBound(0)
            For col = 0 To names.GetUpperBound(row)
                Console.WriteLine(String.Format("{0}{1}{2}{3}{4}", row, vbTab, col, vbTab, names(row, col)))
            Next
        Next

        Console.Write(vbCrLf & vbCrLf & "Array of Arrays" & vbCrLf)

        ' Array of arrays
        Dim days()() As String = New String(1)() {}
        days(0) = New String(1) {}
        days(0)(0) = "Monday"
        days(0)(1) = "Wednesday"

        days(1) = New String(3) {}
        days(1)(0) = "Tuesday"
        days(1)(1) = "Friday"
        days(1)(2) = "Saturday"
        days(1)(3) = "Sunday"

        Console.WriteLine("Row" + vbTab + "Col" + vbTab + "Value")
        For row = 0 To days.GetUpperBound(0)
            For col = 0 To days(row).GetUpperBound(0)
                Console.WriteLine(String.Format("{0}{1}{2}{3}{4}", row, vbTab, col, vbTab, days(row)(col)))
            Next
        Next

        If (System.Diagnostics.Debugger.IsAttached) Then
            System.Diagnostics.Debugger.Break()
        End If

    End Sub

End Module

Below is code for another console app that shows how arrays can be initialised inline with declarations and a way to use For Each loops to iterate the array elements.

Module Module2

    Sub Main()
        'single dimension
        Dim ages() As Integer = New Integer(4) {3, 6, 20, 34, 67}

        Console.WriteLine("Single Dimensional Array")
        For Each age As Integer In ages
            Console.WriteLine(age)
        Next

        Console.Write(vbCrLf & vbCrLf & "Multi Dimensional Array" & vbCrLf)

        'multi dimensional
        Dim names(,) As String = New String(1, 1) {{"Andrew", "Bobby"}, {"Susan", "Peter"}}

        Console.WriteLine("Row" + vbTab + "Col" + vbTab + "Value")
        For Each name As String In names
            Console.WriteLine(name)
        Next

        Console.Write(vbCrLf & vbCrLf & "Array of Arrays" & vbCrLf)

        ' Array of arrays
        Dim days()() As String = { _
            New String() {"Monday", "Wednesday"}, _
            New String() {"Tuesday", "Friday", "Saturday", "Sunday"} _
        }

        Console.WriteLine("Row" + vbTab + "Col" + vbTab + "Value")
        For Each d() As String In days
            For Each day As String In d
                Console.WriteLine(day)
            Next
        Next

        If (System.Diagnostics.Debugger.IsAttached) Then
            System.Diagnostics.Debugger.Break()
        End If
    End Sub
End Module

The example application is available from Github here.

C# Arrays

Firstly some points to note about arrays in C#:

  • C# arrays are zero indexed, meaning 0 is the first index.
  • Array elements are referenced using square brackets [].
  • In declarations the square brackets ([]) come after the type, not the identifier. e.g. string[] cites; and not string cities[];
  • An array can hold other arrays or objects as well as common data objects.
  • Initialisation can be done at the same time as declaration.

Below is a simple console application that demonstrates Single Dimension arrays, Multiple Dimension arrays and Arrays of arrays, also known as Ragged arrays or Jagged Arrays.

using System;

namespace ArraysSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // single dimension
            int[] ages = new int[5];
            ages[0] = 3;
            ages[1] = 6;
            ages[2] = 20;
            ages[3] = 34;
            ages[4] = 67;

            Console.WriteLine("Single Dimensional Array");
            for (int ageLoop = 0; ageLoop < ages.Length; ageLoop++)
            {
                Console.WriteLine(string.Format("Item {0}: {1}", ageLoop, ages[ageLoop]));
            }

            Console.Write("\n\nMulti Dimensional Array\n");

            // multi dimensional
            string[,] names = new string[2, 2];
            names[0, 0] = "Andrew";
            names[0, 1] = "Bobby";
            names[1, 0] = "Susan";
            names[1, 1] = "Peter";

            Console.WriteLine("Row\tCol\tValue");
            for (int row = 0; row < names.GetLength(0); row++)
            {
                for (int col = 0; col < names.GetLength(row); col++)
                {
                    Console.WriteLine(String.Format("{0}\t{1}\t{2}", row, col, names[row, col]));
                }
            }

            Console.Write("\n\nArray of Arrays\n");

            // Array of arrays
            string[][] days = new string[2][];

            days[0] = new string[2];
            days[0][0] = "Monday";
            days[0][1] = "Wednesday";

            days[1] = new string[4];
            days[1][0] = "Tuesday";
            days[1][1] = "Friday";
            days[1][2] = "Saturday";
            days[1][3] = "Sunday";

            Console.WriteLine("Row\tCol\tValue");
            for (int row = 0; row < days.GetLength(0); row++)
            {
                for (int col = 0; col < days[row].GetLength(0); col++)
                {
                    Console.WriteLine(String.Format("{0}\t{1}\t{2}", row, col, days[row][col]));
                }
            }

            if (System.Diagnostics.Debugger.IsAttached)
            {
                System.Diagnostics.Debugger.Break();
            }
        }
    }
}

Output from the above application when run is:

Single Dimensional Array
Item 0: 3
Item 1: 6
Item 2: 20
Item 3: 34
Item 4: 67
Multi Dimensional Array
Row     Col     Value
0       0       Andrew
0       1       Bobby
1       0       Susan
1       1       Peter
Array of Arrays
Row     Col     Value
0       0       Monday
0       1       Wednesday
1       0       Tuesday
1       1       Friday
1       2       Saturday
1       3       Sunday

In the above exmaples the array elements have been set long hand, an element at a time.  It is possible to initialise an array at the same time as the declaration.  Obviously we would only do this if the values were fixed and we knew them from the start.

// single dimension array
int[] ages = new int[4] = {1, 2, 3, 4};
string[] names = new string[4] = {"Andrew", "Bobby", "Susan", "Peter"};

// multi dimension array
int[,] numbers = new int{1, 9] { {2, 8}, {3, 7}, {4, 6}, {5, 5} };
string[,] siblings = new string[2, 2] { {"Mike","Amy"}, {"Mary","Albert"} };

// array of Arrays
int[][] days = new int[2][] { new int[] {1, 2, 3}, new int[] {98, 99, 100} };

Instead of using a for loop to iterate an arry a foreach loop can be used.  This is not as useful on multi dimension arrays because the whole array is treated as one single list.

// single dimension array
foreach (int age in ages)
{
    Console.WriteLine(string.Format("Item {0}", age));
}

// multi dimension array
foreach (string name in names)
{
    Console.WriteLine(name);
}

// array of arrays
foreach (string[] d in days)
{
    foreach (string day in d)
    {
        Console.WriteLine(day);
    }
}

You will notice in the top example the single dimensional array example uses the Length property to get the length of the array.  In the other examples the GetLength method has been used.  The Length property will give the total number of elements in an array  which is 5 in the ages array and 4 in the names array.  The GetLength method accepts an array index (integer) and will return the length of the particular element which in the days array is 2 for the first element and 4 for the second.

ages.Length //5 - Full length of array
ages.GetLength(0) //5 - single dimension so full length of array
ages.GetUpperBound(0) //4 - Index range is 0 to 4
names.Length // 4 - Full length of array
names.GetLength(0) // 2 - Length of elements in first dimension
names.GetUpperBound(0)// 1 - first dimensions index range is 0 to 1
days.Length // 2 - Length of main array	2
days.GetLength(0) // 2 - Length of array in first element
days.GetUpperBound(0) // 1 - Array index range is 0 to 1
days[0].GetUpperBound(0) // 1 - First element array index range is 0 to 1
days[1].GetUpperBound(0) // 3 - Second element array index range is 0 to 3
days[1].Length // 4 - Length of array in First element
days[1].GetUpperBound(0) // 3 - Second element array index range is 0 to 3

An example console application is available from Github here