Index: /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Grammar.cs
===================================================================
--- /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Grammar.cs	(revision 15827)
+++ /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Grammar.cs	(revision 15828)
@@ -166,9 +166,9 @@
 
       // ADDITION
-      if (ReferenceEquals(currentSymbol, Addition)) {
+      if (currentSymbol == Addition) {
         var uniqueChildHashes = new HashSet<THashType>();
 
         // First subtree
-        if (ReferenceEquals(parseStack.Peek(), Addition)) {
+        if (parseStack.Peek() == Addition) {
           uniqueChildHashes.UnionWith(GetSubtreeHashes(parseStack, aggregateHashes));
         } else {
@@ -177,5 +177,5 @@
         }
         // Second subtree
-        if (ReferenceEquals(parseStack.Peek(), Addition)) {
+        if (parseStack.Peek() == Addition) {
           uniqueChildHashes.UnionWith(GetSubtreeHashes(parseStack, aggregateHashes));
         } else {
@@ -190,9 +190,9 @@
 
       // MULTIPLICATION
-      if (ReferenceEquals(currentSymbol, Multiplication)) {
+      if (currentSymbol == Multiplication) {
         var childHashes = new List<THashType>();
 
         // First subtree
-        if (ReferenceEquals(parseStack.Peek(), Multiplication)) {
+        if (parseStack.Peek() == Multiplication) {
           childHashes.AddRange(GetSubtreeHashes(parseStack, aggregateHashes));
         } else {
@@ -200,5 +200,5 @@
         }
         // Second subtree
-        if (ReferenceEquals(parseStack.Peek(), Multiplication)) {
+        if (parseStack.Peek() == Multiplication) {
           childHashes.AddRange(GetSubtreeHashes(parseStack, aggregateHashes));
         } else {
@@ -231,7 +231,7 @@
 
       // LOG, EXP, SIN, INV
-      if (ReferenceEquals(currentSymbol, Log) || ReferenceEquals(currentSymbol, Exp) ||
-          ReferenceEquals(currentSymbol, Sin) || ReferenceEquals(currentSymbol, Cos) ||
-          ReferenceEquals(currentSymbol, Inv)) {
+      if (currentSymbol == Log || currentSymbol == Exp ||
+          currentSymbol == Sin || currentSymbol == Cos ||
+          currentSymbol == Inv) {
         return new[] { aggregateHashes(parseStack.Peek(), GetSubtreeHashes(parseStack, aggregateHashes)) };
       }
@@ -244,5 +244,5 @@
       var hashesArray = hashes.ToArray();
 
-      if ((ReferenceEquals(operatorSym, Addition) || ReferenceEquals(operatorSym, Multiplication)) && hashesArray.Count() <= 1) {
+      if ((operatorSym == Addition || operatorSym == Multiplication) && hashesArray.Length <= 1) {
         return hashesArray[0];
       }
@@ -251,11 +251,10 @@
       }
 
-      return $"[{hashesArray.Aggregate(operatorSym.StringRepresentation, (result, ti) => string.Concat(result, " ° ", ti))}]";      // TODO: use string join instead of string.Concat
+      return $"[{operatorSym.StringRepresentation} ° {string.Join(" ° ", hashesArray)}]";
     }
 
     private int AggregateIntHashes(Symbol operatorSym, int[] hashes) {
       int start;
-      if ((ReferenceEquals(operatorSym, Addition) || ReferenceEquals(operatorSym, Multiplication)) &&
-          hashes.Length <= 1) {
+      if ((operatorSym == Addition || operatorSym == Multiplication) && hashes.Length <= 1) {
         start = 0;
 
@@ -302,31 +301,31 @@
       ISymbolicExpressionTreeNode parsedSubTree = null;
 
-      if (ReferenceEquals(currentSymbol, Addition)) {
+      if (currentSymbol == Addition) {
         parsedSubTree = addSy.CreateTreeNode();
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // left part
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // right part
 
-      } else if (ReferenceEquals(currentSymbol, Multiplication)) {
+      } else if (currentSymbol == Multiplication) {
         parsedSubTree = mulSy.CreateTreeNode();
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // left part
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // right part
 
-      } else if (ReferenceEquals(currentSymbol, Log)) {
+      } else if (currentSymbol == Log) {
         parsedSubTree = logSy.CreateTreeNode();
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
 
-      } else if (ReferenceEquals(currentSymbol, Exp)) {
+      } else if (currentSymbol == Exp) {
         parsedSubTree = expSy.CreateTreeNode();
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
 
-      } else if (ReferenceEquals(currentSymbol, Sin)) {
+      } else if (currentSymbol == Sin) {
         parsedSubTree = sinSy.CreateTreeNode();
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
 
-      } else if (ReferenceEquals(currentSymbol, Cos)) {
+      } else if (currentSymbol ==  Cos) {
         parsedSubTree = cosSy.CreateTreeNode();
         parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
 
-      } else if (ReferenceEquals(currentSymbol, Inv)) {
+      } else if (currentSymbol == Inv) {
         parsedSubTree = divSy.CreateTreeNode();
         ConstantTreeNode dividend = (ConstantTreeNode)constSy.CreateTreeNode();
Index: /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/SearchDataStructure.cs
===================================================================
--- /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/SearchDataStructure.cs	(revision 15827)
+++ /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/SearchDataStructure.cs	(revision 15828)
@@ -5,6 +5,5 @@
 namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.GrammarEnumeration {
 
-  // TODO: struct not useful here because you are boxing the structs with a new call below
-  public struct StoredSymbolString {
+  public class StoredSymbolString {
     public readonly int Hash;
     public readonly SymbolString SymbolString;
@@ -80,9 +79,9 @@
       SymbolString result = storedValues[hash];
       storedValues.Remove(hash);
-      return new StoredSymbolString(hash, result);  // TODO: new for structs creates a box anyway
+      return new StoredSymbolString(hash, result);
     }
 
     public void Store(int hash, SymbolString s) {
-      storeInternal.Invoke(hash); // TODO: explicit .Invoke() not necessary, just storeInternal(hash) is ok
+      storeInternal(hash);
       storedValues[hash] = s;
     }
Index: /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Symbol.cs
===================================================================
--- /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Symbol.cs	(revision 15827)
+++ /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Symbol.cs	(revision 15828)
@@ -1,11 +1,15 @@
-﻿using System.Collections.Generic;
+﻿using System;
+using System.Collections.Generic;
 
 namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
 
-  public abstract class Symbol {
+  public abstract class Symbol : IEquatable<Symbol> {
+    private readonly int stringRepresentationHash;
+
     public string StringRepresentation { get; }
 
     protected Symbol(string representation) {
       StringRepresentation = representation;
+      stringRepresentationHash = representation.GetHashCode();
     }
 
@@ -13,4 +17,32 @@
       return StringRepresentation;
     }
+
+    #region IEquatable
+    public static bool operator ==(Symbol s1, Symbol s2) {
+      return !ReferenceEquals(null, s1) && !ReferenceEquals(null, s2) && (ReferenceEquals(s1, s2)
+        || s1.Equals(s2));
+    }
+
+    public static bool operator !=(Symbol s1, Symbol s2) {
+      return !(s1 == s2);
+    }
+
+    public bool Equals(Symbol other) {
+      if (ReferenceEquals(null, other)) return false;
+      if (ReferenceEquals(this, other)) return true;
+      return string.Equals(StringRepresentation, other.StringRepresentation);
+    }
+
+    public override bool Equals(object obj) {
+      if (ReferenceEquals(null, obj)) return false;
+      if (ReferenceEquals(this, obj)) return true;
+      if (obj.GetType() != this.GetType()) return false;
+      return Equals((Symbol)obj);
+    }
+
+    public override int GetHashCode() {
+      return stringRepresentationHash;
+    }
+    #endregion
   }
 
