Question

I'm developing scientific software that needs access to the periodic table of elements. An Element comprises of a set of Isotopes which have a few readonly properties (e.g. mass, abundance, atomic number, etc.). There are over 100 elements, and when factoring in their isotopes, there are well over 1000 isotopes. To populate all these objects at run time, I currently have an XML file (Build Action: Content)* containing all the elemental data that I parse in during the static constructor of the Element class:

public class Element {

    private static readonly Dictionary<string, Element> _elements;

    static Element()
    {
        _elements = new Dictionary<string, Element>();            
        LoadElements("Resources/Elements.xml");  // 461 KB file    
    }

    static LoadElements(string resource) {
         // code for construction of elements objects and population of the 
         // _elements dictionary.
    }      

    private Element(blah) { \\ instance constructor }

}

This works, but there is a overhead in parsing in the file and I lose some flexibility in designing the Element class. The alternative is to hard-code each Isotope and Element into the static constructor. The advantage of the later is I would be able to add static readonly property for each Element (a useful feature):

 public class Element {

    private static readonly Dictionary<string, Element> _elements;

    public static readonly Element Carbon = {get; private set;}
    public static readonly Element Hydrogen = {get; private set;}

    static Element()
    {
        _elements = new Dictionary<string, Element>();  

        Carbon = AddElement("Carbon", 6);  
        Carbon.AddIsotope(12, 12.0000000, 0.9893);
        Carbon.AddIsotope(13, 13.0033548378, 0.0107);

        Hydrogen = AddElement("Hydrogen", 1);
        //Repeat this pattern for all the elements...
    }

    static Element AddElement(string name, double atomicNumber) 
    {
          Element element = new Element(name, atomicNumber);
          _elements.Add(name, element);
          return element;
    }

    private Element(string name, double atomicNumber) {
         // Not Important, just setting readonly properties
    }

    private void AddIsotope(int massNumber, double mass, double abundance) {
         // Not Important;
    }

}

However, this seems like a lot of hard-coded data to include in a class.cs file. So I am torn, on one hand it makes sense on a data management level to have the elemental data stored in an external file which is read in. But on the other hand, because all the data is really a bunch of constant/static readonly objects, this additional parsing work seems timely, unfruitful, and limits the API design. What is the correct way for creating all these objects?

*Note: the Build Action is set to Content for the case if the client wants to modify the values of the elements for whatever reason. This isn't a necessity and could be changed to an embedded resource.

Was it helpful?

Solution

I would consider putting the values in an embedded file, but possibly having an enum of the elements. (Probably not the isotopes, but provide an easy way of specifying an isotope from the elements.)

That way:

  • You can still have a strongly-typed API, and not rely on magic strings etc in user code
  • You can still make it easy to change the data later should you really wish to (and possibly supply a way of reading the data from an external source)
  • You probably make it easier to work with the data itself, as an XML file rather than C#

Don't worry about the parsing work - given that you only need to do it once, I find it hard to believe that it would be significant in terms of performance.

OTHER TIPS

Check out the blue obelisk project which is hosted on sourceforge - I think you'll find some useful stuff there, possibly even exactly what you're looking for.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top