Blog Archives

Lazy class (advanced)

OK, this is no joke. This class really exists.

Not many programmers come across this class. At first glance it seems to be useless. Let’s have a closer look!
Imagine the following situation. You are initializing objects. Each of them takes a lot of time and uses many resources. There is no load balancing. Some of them may be used simultaneously, so it is not one or the other. The problem is that you don’t know, which object will be needed. It could be that you don’t need any object at all. Nevertheless you want to provide each object to the system as if they were initialized already. That way you don’t have to deal with any initialization later during the running program.

I included a short example about Bill Gates. Let’s say he has too many cars, so he feels the agony of choice. Early in the morning Bill is standing in his garage. He needs a car to go to the beach, but there are simply too many cars to choose from. One of his many gardeners recommends the Porsche. Well, the final choice is at the whim of Bill Gates. Hypothetically he might also need a second car today. His new 19-year-old girl friend had an overnight stay … on the couch. Yeah, that’s life 😉

I am sure you are often using LINQ. It uses a similar concept. Linq does not execute until the point you access the query result. When the example program calls “… select x.GetSomething()”, then you do not see any output from the method GetSomething(), which would be “What about an ice cream?”. “Where is my lunch?” prints first. And when we call lYummy.First() to get the first object from the query (well, there is only one), only then you see GetSomething() executing.

Too Lazy or just right?

using System;
using System.Collections.Generic;
using System.Linq;

namespace DemoApp {
   public class VeryLazy {
      public class NotNow {
         public NotNow() { Console.WriteLine("executing constructor"); }
         public void DoSomething() { Console.WriteLine("Zzzzzz... Jeez, you woke me up!"); }
         public string GetSomething() {
            Console.WriteLine("What about an ice cream?");
            return "ice cream";
         }
      } // class      

      public class BillGatesGarage {
         Lazy<NotNow> Porsche = new Lazy<NotNow>();
         Lazy<NotNow> Ferrari = new Lazy<NotNow>();
         Lazy<NotNow> Maserati = new Lazy<NotNow>();
         Lazy<NotNow> Lamborghini = new Lazy<NotNow>();

         public enum eCoolness { eSmart, eShowOff, eFast, eFun }
         public NotNow getCar(eCoolness xCoolness) {
            Console.WriteLine();
            Console.WriteLine("Sleeping cars:");
            Console.WriteLine("Porsche " + !Porsche.IsValueCreated);
            Console.WriteLine("Ferrari " + !Ferrari.IsValueCreated);
            Console.WriteLine("Maserati " + !Maserati.IsValueCreated);
            Console.WriteLine("Lamborghini " + !Lamborghini.IsValueCreated);
            switch (xCoolness) {
               case eCoolness.eSmart: return Porsche.Value;
               case eCoolness.eShowOff: return Ferrari.Value;
               case eCoolness.eFast: return Maserati.Value;
               case eCoolness.eFun: return Lamborghini.Value;
            }
            return null;
         }
      } // class

      public static void test() {
         List<NotNow> lList = new List<NotNow>();
         lList.Add(new NotNow());         
         var lYummy = from x in lList select x.GetSomething();
         Console.WriteLine("Where is my lunch?");
         Console.WriteLine("I got an " + lYummy.First() + " for you!");

         Console.WriteLine();
         Lazy<NotNow> lLazy = new Lazy<NotNow>();
         Console.WriteLine("Object created already? " + lLazy.IsValueCreated);
         Console.WriteLine("No worries! Let's create an instance now:");
         NotNow lNotNow = lLazy.Value;
         Console.WriteLine("Object created already? " + lLazy.IsValueCreated);
         if (lLazy.IsValueCreated) lNotNow.DoSomething();

         Console.WriteLine();
         Console.WriteLine("All engines warmed up?");
         BillGatesGarage lGarage = new BillGatesGarage();
         NotNow lBrumBrum = lGarage.getCar(BillGatesGarage.eCoolness.eSmart);
         lBrumBrum.DoSomething();
         Console.WriteLine("Oh dear, he just changed his mind");
         NotNow lWhooosh = lGarage.getCar(BillGatesGarage.eCoolness.eFast);
         lWhooosh.DoSomething();

         // check cars
         lGarage.getCar(BillGatesGarage.eCoolness.eFast);
      } //

   } // class
} // namespace

example output:
executing constructor
Where is my lunch?
What about an ice cream?
I got an ice cream for you!

Object created already? False
No worries! Let’s create an instance now:
executing constructor
Object created already? True
Zzzzzz… Jeez, you woke me up!

All engines warmed up?

Sleeping cars:
Porsche True
Ferrari True
Maserati True
Lamborghini True
executing constructor
Zzzzzz… Jeez, you woke me up!
Oh dear, he just changed his mind

Sleeping cars:
Porsche False
Ferrari True
Maserati True
Lamborghini True
executing constructor
Zzzzzz… Jeez, you woke me up!

Sleeping cars:
Porsche False
Ferrari True
Maserati False
Lamborghini True

Advertisements

XML (part 3, basics, advanced), serialize

We are still working with the environment of part 2. We are using the embedded file “Walmart.xml”.

In part 1 we were loading an XML file the following way:

public static void LoadXml() {
    string lDesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\";
    string lFile = lDesktopPath + "Walmart.xml";
 
    XDocument lXDocument = XDocument.Load(lFile);
 
    // food (using WmItem)
    WmItem[] lFood = (from lData in lXDocument.Descendants("Walmart").Descendants("food")
                        select new WmItem(
                            lData.Element("name").Value,
                            double.Parse(lData.Element("price").Value),
                            lData.Element("description").Value)
                ).ToArray();
 
    foreach (WmItem lItem in lFood) Console.WriteLine(lItem);
 
    Console.WriteLine();
 
    // electronic (quick and dirty, using var)
    var lElectronic = from lData in lXDocument.Descendants("Walmart").Descendants("electronic")
                        select lData;
 
    foreach (var lItem in lElectronic) {
        Console.WriteLine(lItem);
        Console.WriteLine();
        Console.WriteLine(lItem.Element("name").Value);
        Console.WriteLine(lItem.Element("price").Value);
        Console.WriteLine(lItem.Element("description").Value);
    }
 
    Console.ReadLine();
} //

LINQ queries were parsing the XML file and initialized the objects.
Well, there is a more direct way out there. Let the .Net framework do the dirty job. Just make use of properties. Here are some of them:

Serializable
Tells that data can be arranged in a sequence. The object can then be sent across networks or be saved.

Xml Attributes

XmlRoot
This is the root of all elements. Each XML file can only have one root element. Compared to hard disk drives on your computer it would be the “C:” directory.

XmlElement
A field or property of an object becomes an XML element during the conversion.

XmlText
A text field. Only one instance of the XmlTextAttribute can be applied in a class.

XmlAttribute
This attribute is self-explanatory. Use it whenever you want to add attributes to XML items.

Add the following two classes in your project. They define the structure of your XML file. You do not have to use attributes for all types. Attributes are optional. This means you can add as many non-Xml-Elements to a class as you like. They are simply ignored during (de-)serialization processes.

[Serializable]
[XmlRoot("Walmart", Namespace = "")]
public class WalmartWorld {
    [XmlElement("food")]
    public List<WalmartItem> Food { get; set; }

    [XmlElement("electronic")]
    public List<WalmartItem> Electronic { get; set; }

    [XmlText]
    public string Text { get; set; }
} // class

[Serializable]
[XmlRoot("Walmart", Namespace = "")]
public class WalmartItem {
    [XmlAttribute("attr")]
    public string Attribute { get; set; }

    [XmlElement("name")]
    public string Name { get; set; }

    [XmlElement("price")]
    public double Price { get; set; }

    [XmlElement("description")]
    public string Description { get; set; }

    [XmlElement("somethingElse")]
    public string SomethingElse { get; set; }

    public override string ToString() {
        return Name.PadRight(12) + 
            Price.ToString("#,##0.00").PadLeft(8) + " " + 
            Description + 
            (string.IsNullOrEmpty(SomethingElse) ? string.Empty : ("  !!! => " + SomethingElse));
    } //
} // class

Step one is to load our embedded file “Walmart.xml” using above classes. The objects will be created for you. There is no need for further parsing or instanciating.

public static WalmartWorld LoadObjects() {
    string lPath = "DemoApp.XmlFiles.Walmart.xml";
    Assembly lAssembly = Assembly.GetExecutingAssembly();

    using (Stream lStream = lAssembly.GetManifestResourceStream(lPath)) {
        XmlSerializer lXmlSerializer = new XmlSerializer(typeof(WalmartWorld));

        using (StreamReader lStreamReader = new StreamReader(lStream)) {

            return lXmlSerializer.Deserialize(lStreamReader) as WalmartWorld;
        }
    }
} //

Above method returns fully initialized classes. Nice, eh?
The code is amazingly short. Let’s convert and save objects on the desktop with this code:

public static void SaveObjects(WalmartWorld xWalmartWorld) {
    string lDesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\";
    string lFile = lDesktopPath + "Walmart2.xml";

    var lXmlSerializer = new XmlSerializer(typeof(WalmartWorld));

    using (var lStreamWriter = new StreamWriter(lFile)) {
        lXmlSerializer.Serialize(lStreamWriter, xWalmartWorld);
    }    
} //

Again, the code could not be shorter.
You can test above methods with the following:

public static void SerializerTest() {
            
    // load
    WalmartWorld lWalmartWorld = LoadObjects();
    if (lWalmartWorld == null) return; // error

    // print results
    foreach (WalmartItem f in lWalmartWorld.Food) Console.WriteLine(f.ToString());
    foreach (WalmartItem e in lWalmartWorld.Electronic) Console.WriteLine(e.ToString());

    // add some stuff
    lWalmartWorld.Text = "Luis Armstrong had a fabulous voice.";
    lWalmartWorld.Food[2].Attribute = "What a wonderful world.";

    // save
    SaveObjects(lWalmartWorld);

    Console.ReadLine();
} //

Have a look at your file “Walmart2.xml”, which was saved onto your desktop. It is not exactly the same as “Walmart.xml”. We added some text and attributes.
Add “Walmart2.xml” to your Visual Studio Solution Explorer and see that you can load it without any trouble. Remember to set the file property “Build Action” to “Embedded Resource”.
You can also use a file stream to load the XML file. The program just gets shorter again, not longer:

public static WalmartWorld LoadXmlAsObject() {
    string lDesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\";
    string lFile = lDesktopPath + "Walmart2.xml";

    XmlSerializer lXmlSerializer = new XmlSerializer(typeof(WalmartWorld));

    using (StreamReader lStreamReader = new StreamReader(lFile)) {
        return lXmlSerializer.Deserialize(lStreamReader) as WalmartWorld;
    }
} //

XML (part 2, basics), embedded, XDocument, XmlDocument, XmlTextReader, XPathNavigator

Embedded

We covered basic file IO for XML files yesterday. This is very useful for settings files. There are some XML files though that you want to hide from the user. I am not talking about encryption. Today we are going to embed the XML file the project itself.
We are still using yesterday’s “Walmart.xml” example. Create a folder “XmlFiles” in your Solution Explorer and drag the file into it.

XmlFileLocation

Now right-click the file “Walmart.xml” and select “Properties”. Change the “Build Action” to “Embedded Resource”.

EmbeddedResourceProperty

Use the following code to load the resource as an XDocument:

// since .Net 3.5
// namespace System.Xml.Linq
// xPath: namespace.folder.file.ext => here: "DemoApp.XmlFiles.Walmart.xml"
public static XDocument getAssemblyXDocument(string xPath) {
    Assembly lAssembly = Assembly.GetExecutingAssembly();
    using (Stream lStream = lAssembly.GetManifestResourceStream(xPath)) {
        XDocument lXDocument = XDocument.Load(lStream);
        return lXDocument;
    }
} //

You can also load the document as an XmlDocument.

// since .Net 1.1
// namespace System.Xml
// xPath: namespace.folder.file.ext => here: "DemoApp.XmlFiles.Walmart.xml"
public static XmlDocument getAssemblyXml(string xPath) {
    Assembly lAssembly = Assembly.GetExecutingAssembly();
    using (Stream lStream = lAssembly.GetManifestResourceStream(xPath)) {
        XmlDocument lXmlDocument = new XmlDocument();
        lXmlDocument.Load(lStream);
        return lXmlDocument;
    }
} //
public static void LoadXmlExample() {
    string lPath = "DemoApp.XmlFiles.Walmart.xml";
    XmlDocument lXml = getAssemblyXml(lPath);
    XDocument lXDoc = getAssemblyXDocument(lPath);
} //

Using an XmlDocument is similar to XDocument. XmlDocument does not support LINQ, which is a big disadvantage.

XmlDocument reads the entire document and initializes a tree structure, which needs a lot of memory. Processing bigger Xml files can cause issues. The tree can be accessed either by browsing through the nodes or by using XPath queries.
You can browse through documents forward/backward and carry out modifications.

XDocument (LINQ to XML) is easy to code and understand. Again the entire document is loaded into memory. To read Xml files we can use the XDocument or XElement class. Both classes support Load() methods. XElement represents an XML fragment while XDocument represents an entire XML document.

XmlTextReader is very fast and memory efficient. Unlike XmlDocument it can only read in forward direction. Searching for something specific is awkward. As the name says, there is no method to write or to modify data. And data validation is also left behind.

XPathNavigator is more complex and slower than XmlReader. XPathNavigator has to read enough data to be able to execute XPath queries. XmlDocument internally uses XPathNavigator. Using XPathNavigator directly is faster than using it via XmlDocument.

Using XmlTextReader:

public static void UseTextReader() {
    string lPath = "DemoApp.XmlFiles.Walmart.xml";
    Assembly lAssembly = Assembly.GetExecutingAssembly();

    using (Stream lStream = lAssembly.GetManifestResourceStream(lPath)) {
        using (XmlTextReader lXmlReader = new XmlTextReader(lStream)) {
            while (lXmlReader.Read()) {
                if (!lXmlReader.IsStartElement()) continue;
                switch (lXmlReader.Name) {
                    case "name":
                        Console.WriteLine("name: " +  lXmlReader.ReadString());
                        break;
                    case "price":
                        Console.WriteLine("price: " + lXmlReader.ReadString());
                        break;
                    case "description":
                        Console.WriteLine("description: " + lXmlReader.ReadString());
                        break;
                    case "somethingElse":
                        Console.WriteLine("somethingElse: " + lXmlReader.ReadString());
                        break;
                    default:
                        Console.WriteLine(Environment.NewLine + lXmlReader.Name);
                        break;
                }
            }
        }
    }
    Console.ReadLine();
} //

example output:

Walmart

food
name: Banana
price: 1.99
description: Mexican delicious

food
name: Rice
price: 0.79
description: the best you can get

food
name: Cornflakes
price: 3.85
description: buy some milk

food
name: Milk
price: 1.43
description: from happy cows

electronic
name: Kindle fire
price: 100
description: Amazon loves you
somethingElse: the perfect Xmas gift for your kids

food
name: baked beans
price: 1.35
description: very British

Using XPathNavigator:

public static void UseXPathNavigator() {
    string lPath = "DemoApp.XmlFiles.Walmart.xml";
    Assembly lAssembly = Assembly.GetExecutingAssembly();

    using (Stream lStream = lAssembly.GetManifestResourceStream(lPath)) {
        XPathDocument lXPathDoc = new XPathDocument(lStream);
        XPathNavigator lXNavi = lXPathDoc.CreateNavigator();
        lXNavi.MoveToRoot();
        lXNavi.MoveToFirstChild();

        do {
            if (lXNavi.MoveToFirstAttribute()) {
                Console.WriteLine(lXNavi.Name + "=" + lXNavi.Value);
                lXNavi.MoveToParent();
            }

            if (!lXNavi.MoveToFirstChild()) continue;
            do {
                if (!lXNavi.MoveToFirstChild()) break;
                do {
                    Console.WriteLine(lXNavi.Name + "=" + lXNavi.Value);
                } while (lXNavi.MoveToNext());
                Console.WriteLine();
                lXNavi.MoveToParent();
            } while (lXNavi.MoveToNext());
            lXNavi.MoveToParent();
        } while (lXNavi.MoveToNext());

        Console.ReadLine();
    }
} //

example output:
name=Banana
price=1.99
description=Mexican delicious

name=Rice
price=0.79
description=the best you can get

name=Cornflakes
price=3.85
description=buy some milk

name=Milk
price=1.43
description=from happy cows

name=Kindle fire
price=100
description=Amazon loves you
somethingElse=the perfect Xmas gift for your kids

name=baked beans
price=1.35
description=very British

Using XPathNavigator with query:

public static void UseXPathNavigator(string xQuery) {
    string lPath = "DemoApp.XmlFiles.Walmart.xml";
    Assembly lAssembly = Assembly.GetExecutingAssembly();

    using (Stream lStream = lAssembly.GetManifestResourceStream(lPath)) {
        XPathDocument lXPathDoc = new XPathDocument(lStream);
        XPathNavigator lXNavi = lXPathDoc.CreateNavigator();

        XPathNodeIterator lIterator = lXNavi.Select(xQuery);

        if (lIterator.Count <= 0) {
            Console.WriteLine("Nothing found!");
            return;
        }

        while (lIterator.MoveNext()) {
            Console.WriteLine(lIterator.Current.Value);
        }
    }            
} //

public static void TestQueries() {
    UseXPathNavigator(@"/Walmart/electronic");
    Console.WriteLine();
    UseXPathNavigator(@"/Walmart/food[name='Banana']");
            
    Console.ReadLine();
} //

example output:
Kindle fire100Amazon loves youthe perfect Xmas gift for your kids

Banana1.99Mexican delicious

My opinion is: Make use of LINQ to XML. It is very comfortable and can save you a lot of time. If you have a lot of data, then you should consider a database rather than XML files.

We will discuss XML object serialization tomorrow. Let C# save and load objects the nice way.

PLINQ (basics)

Language-Integrated Query (LINQ) has been implemented into C# to perform queries over any kind of data like eg. objects or databases. Parallel Language-Integrated Query (PLINQ) is a further approach to access objects. As the name tells us already, it has to do with parallelism. The evolution from sequential queries (LINQ) to parallel queries (PLINQ) was predictable. Extension methods for PLINQ are defined in the class System.Linq.ParallelEnumerable.

public static void PLINQ1() {
    int[] range = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    Console.WriteLine("old school");
    for (int i = 0, n = range.Length; i < n; i++) {         if (range[i] % 2 == 0) Console.WriteLine(range[i]);     }     Console.WriteLine("LINQ");     var linq = from i in range where (i % 2 == 0) select i;     foreach (int i in linq) Console.WriteLine(i);     Console.WriteLine("LINQ2");     var linq2 = range.Where(i => i % 2 == 0);
    foreach (int i in linq2) Console.WriteLine(i);

    Console.WriteLine("PLINQ1");
    var plinq = from i in range.AsParallel() where (i % 2 == 0) select i;
    foreach (int i in plinq) Console.WriteLine(i);

    Console.WriteLine("PLINQ2");
    var plinq2 = range.AsParallel().Where(i => i % 2 == 0);
    foreach (int i in plinq2) Console.WriteLine(i);

    Console.WriteLine("PLINQ3");
    var plinq3 = range.AsParallel().Where(i => { Thread.Sleep(1000); return (i % 2 == 0); });
    foreach (int i in plinq3) Console.WriteLine(i);

    Console.WriteLine("PLINQ3 sorted");
    var plinq3sorted = range.AsParallel().AsOrdered().Where(i => { Thread.Sleep(1000); return (i % 2 == 0); });
    foreach (int i in plinq3sorted) Console.WriteLine(i);

    Console.ReadLine();
} //

Interestingly the runtime decides by itself if it makes sense to execute your query as parallel. Thus parallel execution is not guaranteed unless you specify WithExecutionMode(ParallelExecutionMode.ForceParallelism).
You can even get more specific by using WithDegreeOfParallelism() and limit the number of processors being used.

public static void PLINQ2() {
    var range = Enumerable.Range(0, 25);
    var result = range.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism).Where(i => i % 2 == 0);
    //var result = range.AsParallel().WithDegreeOfParallelism(4).Where(i => i % 2 == 0);
    //var result = range.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism).WithDegreeOfParallelism(4).Where(i => i % 2 == 0);
    foreach (int i in result) Console.WriteLine(i);

    Console.ReadLine();
} //

And now we are facing something weird. We created a sorted result, but somehow the sorting gets lost! The reason is that unlike “foreach” ForAll() does not wait for all results before it starts executing.
Hence we see an unexpected result.

public static void PLINQ3() {
    var range = Enumerable.Range(0, 25);

    var plinq2sorted = range.AsParallel().AsOrdered().Where(i => { Thread.Sleep(1000); return (i % 2 == 0); });
    Console.WriteLine("sorted");
    foreach (int i in plinq2sorted) Console.WriteLine(i);
    Console.WriteLine("something is going wrong?");
    plinq2sorted.ForAll(i => Console.WriteLine(i));

    Console.ReadLine();
} //

example output:
sorted
0
2
4
6
8
10
12
14
16
18
20
22
24
something is going wrong?
6
0
4
2
14
10
12
8
22
18
16
20
24

Parallel queries can fail and throw exceptions. These exceptions will not stop the execution of the queries. They are collected and returned in one single Exception that can be caught by the usual try/catch block.

public static void PLINQ4() {
    var range = Enumerable.Range(0, 25);

    try {
        var plinq2sorted = range.AsParallel().AsOrdered().Where(i => {
            Thread.Sleep(500);
            if (i > 15) throw new ArgumentException("exception for number " + i);
            return (i % 2 == 0);
        });

        foreach (int i in plinq2sorted) Console.WriteLine(i);
    }
    catch (AggregateException e) {
        Console.WriteLine("Exception thrown for " + e.InnerExceptions.Count + " results");
        foreach (var innerException in e.InnerExceptions) Console.WriteLine(innerException.Message);
    }

    Console.ReadLine();
} //

example output:
Exception thrown for 8 results
exception for number 16
exception for number 20
exception for number 17
exception for number 21
exception for number 19
exception for number 23
exception for number 22
exception for number 18