blog

Categories     Timeline     RSS

Operator overloading madness

Some madness concerning operator overloading in C# that I tripped over today: Let’s say we (tragically) have to work with XML stuff in a certain namespace. You define the namespace to use it later.

using System;
using System.IO;
using System.Xml.Linq;

namespace Madness {
	public class WTF {
		public static void Main(String[] args) {
			XNamespace foo = "foo";
			Console.WriteLine(foo + "bar");
		}
	}
}

You combine the namespace with some element name to arrive at your destination. The code sits for a while, later you decide to look at it again. You’re in a fit to throw out everything that is not needed, so you replace the concrete type XNamespace for implicit typing with var.

using System;
using System.IO;
using System.Xml.Linq;

namespace Madness {
	public class WTF {
		public static void Main(String[] args) {
			var foo = "foo";
			Console.WriteLine(foo + "bar");
		}
	}
}

After all, this should be the same, right? Wrong.

0 % ./madness
{foo}bar

0 % ./madness2
foobar

The reason: The first version implicitly converts a string to an XNamespace and uses the + operator provided by that class. In the second version, foo is of type string and the normal string concatenation is used. The combination of implicit conversion at assignment and overloaded ‘+’ operators really made this one hard to spot.

Compiling C# code at runtime

The following is a minimal example of compiling C# code stored in a string at runtime. The result is a full-fledged assembly, which can be accessed and used via reflection.

using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;

public class Metaprogramming {
  public static void Main() {
    var test = @"

      using System.IO;
      namespace Test {

        public class Foobar{
          public static void Main() {
            using (var writer = File.CreateText(""compiletest.txt"")) {
              writer.WriteLine(""success"");
            }
          }
        }
      }
    ";

    var csc = CodeDomProvider.CreateProvider("CSharp");
    var options = new CompilerParameters();
    var res = csc.CompileAssemblyFromSource(options, test);
    var type = res.CompiledAssembly.GetType("Test.Foobar");
    type.GetMethod("Main").Invoke(null, null);
  }
}

Running the above code will result in a file compiletest.txt, which was created by the code stored in the string test.

% ./example.exe
% cat compiletest.txt
success

If you need references to other assemblies for your code, you can pass those assemblies to the compiler parameters:

options.ReferencedAssemblies.AddRange(assemblies);

Second Power Rack

I had rack uprights left over from an upgrade of my power rack, so I decided to make a second power rack with DIY crossbeams. Cost was one factor in deciding to do it myself, but I also think the Rogue Monster Lite measures are a little off (a tad too wide sideways and either too long or not long enough front to back). 6cm square tubing with some flat steel welded on the ends fits nicely into the ensemble.

Mein Buchclub hat ein Wanderproblem

Panorama-Route um Bad Lippspringe. Bei 1°C und zugigen Verhältnissen auf der Hochebene doch teils schattig. Die Strecke ist unspektakulär, läuft sich dafür aber angenehm. Noaks Pumpe lieferte leider kein Wasser. Zur eigentlichen Bücherbesprechung sind wir dann kaum gekommen - stellt sich raus, dass zügiges Gehen nicht gut zu konzentrierter Besprechung passt.

Coaster

A single malt needs a proper coaster.

Plum, oiled

< Older

Newer >