Posts

Returning an IEnumerable from a database

This is probably rather obvious, but... when returning an `IEnumerable` from a database, like the records from a table, don't do this: using (var db = GetDatabase()) { return db.GetTable("Table1"); } because it will throw an exception when trying to enumerate those records, since the database connection has already been disposed. Don't do this either: using (var db = GetDatabase()) { return db.GetTable("Table1").ToList(); } because it will retrieve all records from the table, even if you only need a small subset. A slightly better way is to do this: using (var db = GetDatabase()) { foreach (var item in db.GetTable("Table1")) yield return item; } This way, the `Dispose` method doesn't get called until the enumeration is over and if you only `Take()` a limited number of records from the result, it won't load the whole table. On the other hand, if you only add `Where()` clauses to the result, it will still enumerate every...

Aligning text

I needed to write some code in a console app to align what a user was saying, in case it was longer than a line (80 characters): marcel: blah blah blah a lot of text that doesn't fit in 80 characters more blah blah blah long_username: Contrary to popular belief, Lorem Ipsum is not simply random text . It has roots in a piece of classical Latin literature from 45 B C, making it over 2000 years old. Richard McClintock, a Latin pro fessor at Hampden-Sydney College in Virginia, looked up one of th I wrote the code in two ways: an imperative, mutating style and a functional (recursive) style. I find the second one to be more elegant but since the entire project is something done as a hobby I don't much care about speed; your mileage might vary. I'm also quite certain the first method can be improved but… again, I don't need to do that so it doesn't get done. As usual, use at your own risk, I don't care about c...

Math is a game

Math is a game, an arbitrary set of symbols and rules. The weird part, the part that always surprises me, is that it's relevant to the real world. Here's an example: we'll start with just two symbols, Yin and Yang. (Replace those with black and white, circle and square, X and Y… whichever two symbols you prefer.) What can we do with them? Well, the simplest thing we can do is transform one into the other: Yin → Yang; Yang → Yin We'll call this transformation "mirroring" and denote it with the letter "M". What about combining two symbols? We have a number of possibilities: A) Yin, Yang → Yin; Yang, Yin → Yin; Yin, Yin → Yin; Yang, Yang → Yin This is rather boring… no matter what we start with, we obtain an Yin symbol. Nevertheless, let's continue. B) The opposite of A: Yin, Yang → Yang; Yang, Yin → Yang; Yin, Yin → Yang; Yang, Yang → Yang. Still boring. C) Yin, Yang → Yin; Yang, Yin → Yin; Yin, Y...

Parsing INI files

I am trying to allow the end user to modify the application behavior in some limited ways; as such, I have a need of parsing .INI files of the form [Type 1] contains=abc contains=def [Type 2] contains=1234 I looked around for a class / library that would allow me to read these files but I haven't found anything useful (most of the classes I found couldn't handle duplicate keys within the same section). As such, I went ahead and implemented this myself. This algorithm is extremely specific to my usage, you might have to modify it for your needs. The IniTuple represents each line as a (section, key, value) tuple: public class IniTuple { public string Section { get; private set; } public string Key { get; private set; } public string Value { get; private set; } public IniTuple(string section, string key, string value) { Section = section; Key = key; Value = value; } } The IniP...

C# math is fast

I was reading an article on neural networks that mentioned the usual sigmoid activation function when the inputs are real numbers in the [0, 1) interval: 1 / (1 + e −x ) The article mentions that this is probably where the program would spend at least half of its time so I thought "why not pre-compute a bunch of values and trade memory and precision for time"? It turns out, C# math is quite fast and the gain might not be worth it. (I haven't tested it yet with a NN.) This is the code I wrote to benchmark the two options, using LinqPad 5 : void Main() { const int STEPS = 1 * 1000 * 1000; Func<double, double> activation = x => 1.0 / (1.0 + Math.Exp(-x)); var cache = Precompute(0.0, 1.0, STEPS, activation); Benchmark("Using the cache", x => cache[(int) Math.Truncate(x * STEPS)]); Benchmark("Calling the function each time", activation); } double[] Precompute(double lower, double upper, int steps, Func<dou...

A simple rules engine

I'm extracting data from some OCR'd letters and, in order to determine which type of letter I'm parsing, I'm using a method similar to this: public Letter Parse(string text) { Letter result; if (text.IndexOf("...", StringComparison.OrdinalIgnoreCase) >= 0) letter = new LetterA(); else letter = new LetterB(); //... additional processing return letter; } If the letter contains a specific text, I know it's of one type; otherwise I'll default to the other type. Unfortunately that's going to get really complicated, really fast once I start adding new letter types. I read somewhere that "you should move logic out of the code and into the data when possible"; it made sense and I never had a reason to regret it. So, let me try to do that here. First I'll add a "rules list" class that will allow me to store the ...

Crystal Reports woes

This took me an hour to figure out so I thought I'd write it down in case it helps anyone else. If you have a form that's going to display a Crystal Report and you want to zoom it by default, the "normal" way would be to do this in form_Shown: private void ReportViewer_Shown(object sender, EventArgs e) { viewer.Zoom(2); // 1 = page width, 2 = whole page, 25..400 = zoom factor } (Where viewer is the CrystalReportViewer component.) Unfortunately, it takes CR a while to compute and display the actual report; by the time that happens, the .Zoom() call has already been executed (and ignored). I have tried a number of workarounds (including launching a thread, waiting for two seconds and then calling the Zoom method - it worked but it was a horrible hack) before I discovered that CR has a "hidden" PageChanged event (it has a [Browsable(false)] attribute). Use that event by assigning a handler in the constructor: viewer.PageCha...