10 utilities C# developers should know, part two

This post is part two of a series on general purpose C# utilities. Part one is here. As a note, the implementations shown below are missing things like argument validation in favor of brevity. For more complete implementations, check out https://gist.github.com/madelson/9178059. This also includes the utilities from part 1.


EqualityComparers.Create
Most of the built-in .NET collections and LINQ extension methods come with the option of specifying a custom IEqualityComparer. This adds a ton of flexibility, meaning that you can, for example, trivially customize OrderBy to be case-insensitive or Distinct() to compare only select properties of an object. Unfortunately, this flexibility is burdened by the cumbersome effort of actually implementing IEqualityComparer, which is hard to do in under ~15 lines of code. Enter EqualityComparers.Create(), which makes it easy to define custom comparers on the fly using concise lambda expressions:

public static class EqualityComparers
{
    public static IEqualityComparer<T> Create<T>(
                    Func<T, T, bool> equals, 
                <a href="http://www.codeducky.org/hello-world/">World!</a>       Func&lt;T, int&gt; hash = null)
    {
        return new FuncEqualityComparer&lt;T&gt;(equals, hash ?? (t =&gt; 1));
    }

    private class FuncEqualityComparer&lt;T&gt; : EqualityComparer&lt;T&gt;
    {
        private readonly Func&lt;T, T, bool&gt; equals;
        private readonly Func&lt;T, int&gt; hash;
    
        public FuncEqualityComparer(Func&lt;T, T, bool&gt; equals,  <a href="http://www.wholesalejerseysdiscount.us.com">cheap nfl jerseys</a>  Func&lt;T, int&gt; hash)
        {
            this.equals = equals;
            this.hash = hash;
        }
    
       <a href="http://mixminder.com/capital-letter-c/">C</a>    public override bool Equals(T a, T b)
        {
            return a == null 
                ? b == null 
        : b != null &amp;&amp; this.equals(a, b);
        }
        
        public override int GetHashCode(T obj)
        {
            return obj == null ? 0 : this.hash(obj);
        }
    }
}

For example, to create a dictionary that compares Tuples by only their first member, you can do:

var dict = new Dictionary&lt;Tuple&lt;int, int&gt;, object&gt;(
    EqualityComparers.Create&lt;int&gt;(
        equals: (a, b) =&gt; a.Item1 == b.Item1, 
       <a href="http://www.dallascowboysjerseyspop.com">wholesale mlb jerseys</a>    hash: t =&gt; t.Item1));

Null values are handled automatically, which simplifies the implementation. Providing a hash function is optional, since implementing GetHashCode() may or may not be useful depending on the algorithm using the comparer. Even when it is useful, a custom hash function is only an optimization, which may not be necessary in some cases. Finally, the common case of creating a comparer that compares values by some key selector function can be implemented on top of this as a 1-liner:

public  <a href="http://www.cheapelitejerseys.us.com">cheap nba jerseys</a>  static IEqualityComparer&lt;T&gt; Create&lt;T, TKey&gt;(Func&lt;T, TKey&gt; keySelector)
{
    return Create&lt;T&gt;(
      equals: (a, b) =&gt; EqualityComparer&lt;TKey&gt;.Default.Equals(keySelector(a), 
                                                              keySelector(b)),
      hash: t =&gt; EqualityComparer&lt;TKey&gt;.Default.GetHashCode(keySelector(t)));
}

CollectionEquals
Frustratingly, the BCL doesn’t contain a nice method for comparing collections. ISet has a SetEquals method that, by definition, ignores duplicates, while Enumerable.SequenceEqual is useful only when order matters. Here’s a simple implementation of CollectionEquals, which checks whether two sequences have the same elements independent of order:

public static bool CollectionEquals&lt;T&gt;(this IEnumerable&lt;T&gt; @this, 
                                       IEnumerable&lt;T&gt; that, 
              <a href="http://bowling-auberville.com/class-aptent-taciti-sociosqu-ad-litora/">Litora</a>                            IEqualityComparer&lt;T&gt; comparer = null)
{
    //this is optional; if you want to be consistent with SequenceEqual, 
    //just throwexceptions if either argument is null instead
    if (@this == null) { return that == null; }
    else if (that == null) { return false; }
    
    var countedItems = @this.GroupBy(t =&gt; t, comparer).ToDictionary(
            g =&gt; g.Key, 
            g =&gt; g.Count(), 
            comparer);
    foreach (var item in that)
    {
        int count;
        if (!countedItems.TryGetValue(item, out count)) { return false; }
        if (count - 1 == 0) { countedItems.Remove(item); }
      <a href="http://www.codeducky.org/10-utilities-c-developers-should-know-part-one/">know,</a>     else { countedItems[item] = count - 1; }
    }
    return countedItems.Count == 0;
}

There are obviously many ways to write this; this one is fairly concise and O(N + M) time assuming that we have a good hash function for the collection elements. The other nice thing about this implementation is that it’s very easy to evolve into an Assert utility for checking collection equality in unit tests. With natural points for capturing (1) items in @this and not in that and (2) items in that and not in @this, it’s easy to fail with a very helpful error message explaining why the mismatch occurred.

GetOrAdd
Dictionaries are frequently used for caching and memoization. You’ve no doubt come across the following pattern in code:

SomeType value;
if (!dictionary.ContainsKey(key))
{
    value = ComputeValue(key);
    dictionary[key] = value;
}
else 
{
    value = dictionary[key];
}

While this code can be made a bit more efficient with TryGetValue, it’s still not chainable and ends up being written over and over again. Interestingly, the ConcurrentDictionary class has a nice wrapper for this logic called GetOrAdd(), which takes a key and a value factory function so that this operation becomes a chainable one-liner. I’ve written an extension which grants this functionality to all IDictionaries:

public static TValue GetOrAdd&lt;TKey, TValue&gt;(
        this IDictionary&lt;TKey, TValue&gt; @this, 
        TKey key, 
        Func&lt;TKey, TValue&gt; valueFactory)
{
    TValue value;
    if (!@this.TryGetValue(key, out value)) 
    { 
        @this.Add(key, value = valueFactory(key)); 
    }
    return value;
}

With this, the pattern above reduces to:

var value = dictionary.GetOrAdd(key, ComputeValue);

Note that I’ve explicitly made the signature of this function identical to the one on ConcurrentDictionary. That way, users of ConcurrentDictionary will not mistakenly use this function, which is not thread-safe (due to the use of Add) and would likely do more synchronization work than the builtin method.

GetMethod
Reflection is a powerful aspect of .NET, and vital for many tasks like model binding, serialization, and processing expression trees. However, I’ve always been frustrated by the fact that using reflection makes code ????? harder to refactor since your method and property names end up as strings. This method leverages Expression lambdas to allow for type-safe retrieval of properties.

public static MethodInfo GetMethod&lt;TInstance&gt;(
        Expression&lt;Action&lt;TInstance&gt;&gt; expr)
{
    return (MethodInfo)((MethodCallExpression)expr.Body).Method;
}

Not only does this add type-safety to many reflection scenarios, but it also simplifies the handling of overloads because the compiler will do the overload resolution for you. For example, let’s say you wanted to retrieve the overload of
Queryable.Max that takes a selector function:

var method = Helpers.GetMethod(
    (IQueryable&lt;object&gt; q) =&gt; q.Max(default(Func&lt;object, object&gt;)));

From here, it’s easy to see how you can build out similar functions for retrieving PropertyInfos and non-extension static methods.

GetGenericArguments
System.Type already has a GetGenericArguments() method, so why do we need another one? Using the native GetGenericArguments() in generic code can be difficult because a single type can have multiple sets Six of generic parameters. For example, IDictionary implements IEnumerable<KeyValuePair>. Thus, if you use the following code to determine the element type of an IEnumerable, it will fail if the given enumerable is a Dictionary:

// returns typeof(int) for a Dictionary&lt;int, int&gt;, instead of the desired
// typeof(KeyValuePair&lt;int, int&gt;)
var elementType = enumerable.GetType().GetGenericArguments()[0];

The GetGenericArguments() below method makes it easy to do this kind of logic robustly by allowing you to specify which generic type definition you actually care about when fetching generic arguments:

public static Type[] GetGenericArguments(this Type @this, 
                                         Type genericTypeDefinition)
{
    if (genericTypeDefinition.IsInterface)
    {
        var @interface = @this.GetInterfaces()
                .FirstOrDefault(i =&gt; 
                    i.IsGenericType &amp;&amp;
                    i.GetGenericTypeDefinition() == genericTypeDefinition);
        return @interface.NullSafe(i =&gt; i.GetGenericArguments(), 
                                   Type.EmptyTypes);
    }
    if (@this.IsGenericType &amp;&amp;
        @this.GetGenericTypeDefinition() == genericTypeDefinition)
    {
        return @this.GetGenericArguments();
    }
    return @this.BaseType.NullSafe(
        t =&gt; t.GetGenericArguments(genericTypeDefinition), 
        Type.EmptyTypes);
}

Using this function, we can fix our element type-fetching code above:

var elementType = enumerable.GetType()
                            .GetGenericArguments(typeof(IEnumerable&lt;&gt;));

This functionality can also be used to test whether a given type extends or implements some generic type:

// this doesn&#039;t work, since it returns false
var isIDictionary = typeof(IDictionary&lt;,&gt;)
    .IsAssignableFrom(typeof(Dictionary&lt;int, int&gt;))

// this works correctly
var isIDictionary = typeof(Dictionary&lt;int, int&gt;)
    .GetGenericArguments(typeof(IDictionary&lt;,&gt;))
    .Any();

Even when the native GetGenericArguments() will always work correctly, I find myself using this version where possible for enhanced readability. Deep in reflection code, it quickly becomes easy to forget which types you’re actually dealing with. Specifying the generic type definition makes the code more readable because it’s more obvious what the result will be:

// not that readable
var returnType = someParameterInfo.GetGenericArguments()[2]
// more readable
var returnType = someParameterInfo.GetGenericArguments(typeof(Func&lt;,,&gt;))[2] 
Mike Adelson

Mike Adelson

Software Engineer at Applied Predictive Technologies
I'm a software engineer at Applied Predictive Technologies in Washington D. C., where I work on "big data" analytics and.NET web development. In my spare time, I enjoy reading, working on various side projects, and answering questions on StackOverflow.
Mike Adelson

Latest posts by Mike Adelson (see all)

7 thoughts on “10 utilities C# developers should know, part two

  1. This is awesome! I created 2 generic methods for doing implicit conversions, based on your code. Is there a more simple way?

    public static TTo ImplicitCast(object value)
    {
    var type = value.GetType();
    var method = GetMethod(() => ImplicitCast(null))
    .GetGenericMethodDefinition()
    .MakeGenericMethod(type, typeof(TTo));

    var result = method.Invoke(null, new[] { value });
    return (TTo)result;
    }

    public static TTo ImplicitCast(TFrom value)
    {
    // based on the IL produced by:
    // dynamic list = new List();
    // list.Add(default(TFrom));
    // We can’t use the above code because it will mimic a cast in a generic method
    // which doesn’t have the same semantics as a cast in a non-generic method

    var list = new List(capacity: 1);
    var binder = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
    flags: CSharpBinderFlags.ResultDiscarded,
    name: “Add”,
    typeArguments: null,
    context: typeof(ClassTools), // the current type
    argumentInfo: new[]
    {
    CSharpArgumentInfo.Create(flags: CSharpArgumentInfoFlags.None, name: null),
    CSharpArgumentInfo.Create(
    flags: CSharpArgumentInfoFlags.UseCompileTimeType,
    name: null
    )
    }
    );
    var callSite = CallSite<Action>.Create(binder);
    callSite.Target.Invoke(callSite, list, value);
    return list[0];
    }

    1. Hi Lauri,

      I’m glad you like the code! Were you referring to this post: http://www.codeducky.org/dynamically-determining-implicit-explicit-type-conversions-c/? Your approach looks generally reasonable as far as adapting the code to perform the casts rather than just detect them. Note that it may be possible to do this a bit more simply using expression trees (check out Expression.Convert and Expression.Compile), but I’m not sure; they are not sufficient for detecting conversions. Probably the best way to check is to run the code through an test suite similar to what I used for my code and see where the holes are.

  2. Nice 🙂 However, I have a suggestion on the CollectionEquals method. You could still make an extension method for IEnumerable to check for equality of sequence members; irrespective of order, fast and the added advantage to check lazily. Below is a sample of my “Equality” extension method.

    public static bool IsEquivalentOf(this IEnumerable first, IEnumerable second, IEqualityComparer comparer = null)
    {
    return first.Intersect(second, comparer).Count() == first.Count();
    }

    1. Intersect is a very nice method for this sort of thing. However, I will note that the implementation in the post has a few advantages/differences:

      * Duplicate Handling: the intersect approach you mention ignores duplicates in second (we could address this by also checking second.Count())
      * Multiple Enumeration: with this implementation we end up enumerating first twice. That’s fine if first is a collection, but not so great if it’s a lazy enumerable or database-backed IQueryable. We could address this by saving off first.ToList() and second.ToList() upfront to avoid this.
      * Short-circuiting: the posted implementation will exit as soon as a mismatch is detected. Because the Intersect approach compares counts, we can’t exit until we’ve fully enumerated both sequences.

  3. private class FuncEqualityComparer : EqualityComparer

    must be

    private class FuncEqualityComparer : IEqualityComparer

    1. In this case, I’m purposefully extending the EqualityComparer[T] class rather than the IEqualityComparer[T] interface. The main benefit of this is that the class also implements the non-generic IEqualityComparer interface, which is occasionally useful.

Leave a Reply