Archive for the ‘extension methods’ Tag
Combining Ordered Lists in .NET
I recently came across an issue with LINQ involving the combination of ordered (sorted) lists. The problem does not seem to have a simple solution within the core libraries of .NET 3.5, so I decided to write my own (short) function to accomplish the task. Extensions methods and the static Enumerable class usually contain all the possible methods you might need for dealing with lists (or more generally enumerable collections). Combining ordered lists, however, isn’t quite so straightforward a process (to do efficiently) as it might first seem. Of course, you could simply do Enumerable.Concat(listA, listB).OrderBy(keySelector) but it should be apparent that this is very inefficient for large lists if you know your lists are already ordered. Moreover, the call will never return if either or both of the enumerable collections you pass are of infinite length. What you really want to do is select items from the lists by switching back and forth between them, picking whichever of the next items ought to come first (which is determined by the key selector and associated IComparable implementation).
public static IEnumerable<TSource> CombineOrdered<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector) where TKey : IComparable<TKey> { var firstEnumerator = first.GetEnumerator(); var secondEnumerator = second.GetEnumerator(); var firstCanAdvance = firstEnumerator.MoveNext(); var secondCanAdvance = secondEnumerator.MoveNext(); var firstCurKey = keySelector(firstEnumerator.Current); var secondCurKey = keySelector(secondEnumerator.Current); while (true) { if (firstCanAdvance && (!secondCanAdvance || firstCurKey.CompareTo(secondCurKey) <= 0)) { yield return firstEnumerator.Current; firstCanAdvance = firstEnumerator.MoveNext(); if (firstCanAdvance) firstCurKey = keySelector(firstEnumerator.Current); } else if (secondCanAdvance) { yield return secondEnumerator.Current; secondCanAdvance = secondEnumerator.MoveNext(); if (secondCanAdvance) secondCurKey = keySelector(secondEnumerator.Current); } else { yield break; } } }
To use the function, for example within a static class named Enumerable2, you can call it as such:
Note: The given implementation needs to take lists sorted in an ascending order and returns a combined list in the same order. To sort descending, change the <= sign to a >= sign in the code and insure that you pass lists sorted in a descending order.
Leave a Comment
Searching for Exceptions in .NET
Filed under: Programming, Software | Tags: .net, c#, cil, clr, control flow, errors, exceptions, extension methods, instructions, libraries, methods, msil, reflection, stack, stackoverflow, third-party libraries, try-catch, variables, xml comments, xml documentation
I recently came across a rather interesting question on StackOverflow that posed the problem of discovering all the exceptions that a given method might throw under every circumstance.
Of course, in the great majority of situations, XML documentation for the BCL (and ideally any third-party libraries too) should provide information about any exception that might be thrown and any potential reason for it. Indeed, thisthis is generally all one needs to write largely error-safe code. However, not every exception is documented in any case, and for production-quality applications, it is often desirable to insure that there is no realistic chance of an unhandled exception ocurring. For this reason, it is sometimes desirable to do a rigorous check for all exceptions. Clearly, an application-level unhandled (fatal) exception handler would do the job to some extent, and although this is always a good fallback feature to have, it is the least elegant solution to coping with exceptions.
After some consideration, it became quite apparent that the task reduces to the halting problem. However, with a few simplifications, the problem does become relatively solvable. Most importantly, complex logic that determines whether an exception will be thrown must be ignored, and one must simply assume that any throw statement within a given method could possibly cause an exception under certain conditions.
Here is the complete code for the algorithm I wrote. The GetAllExceptions method is an extension method that returns a read-only collection of exceptions, which makes it very straightforward and efficient to use.
Notably, the code detects all of
Exceptions are only counted when the appropiate throw instruction is encountered at some level. Also, the stack and local variables are handled correctly, as far as I can tell, so this method should work soundly in pretty much all cases. (It has been tested with some a few quite complex methods within the BCL, as well as simpler user-defined ones.)
To be quite honest, I’m not sure whether I’ll need to use this code myself at any point, but I’ve posted it regardless for the benefit of anyone who might require such rigorous exception checking. It was definitely an interesting challenge, at the least.
Any further comments or suggestions would be welcome, as always.