{"id":104,"date":"2012-01-28T10:07:29","date_gmt":"2012-01-28T16:07:29","guid":{"rendered":"http:\/\/kratzindustries.com\/CodeRedBlog\/?p=104"},"modified":"2014-03-27T04:35:50","modified_gmt":"2014-03-27T04:35:50","slug":"lambda-expressions-for-easy-custom-sorts","status":"publish","type":"post","link":"https:\/\/burnt-traces.com\/?p=104","title":{"rendered":"Lambda Expressions for Easy Custom Sorts"},"content":{"rendered":"<p>If you&#8217;re like me, then you like to experiment with new and different ways to do the usual programming tasks that you do. Perhaps its just a reaction to the boredom of always doing things the same way. Sometimes its an attempt to make the easy but time consuming tasks faster. Often is in a search for better looking, more abstract code. I like to think of it as a learning opportunity. The other day I was playing with sorting a list of objects. There are build in ways to do this in the <code>List(Of T)<\/code> class, so I though I would experiment with the different overloads of the <code>List(Of T).Sort()<\/code> method. While what is provided by the .NET Framework is adequate to make clean code, I played around anyways because you never know when you will run into something that doesn&#8217;t give you a clean solution out of the box. So just in case, its good to add more tools to your mental utility belt, at least that&#8217;s what I tell myself so it doesn&#8217;t feel like I&#8217;m wasting time.<\/p>\n<p>For sorting an object based on an arbitrary property, the <code>Sort()<\/code> is not helpful as you cannot specify how the comparison is to be made. So that takes us to the first overload, <code>Sort(IComparer(Of T))<\/code>. This method is probably too cumbersome for standard adhoc and one time sorts that you may have to do. It requires that you pass it an instance of a class that implements <code>IComparer(Of T)<\/code>, and the <code>Compare<\/code> method of that class will define your comparisons. One of my favorite features in .NET is generic types, as it increases code reuse substantially. So, why not make a generic class that takes a lambda function in the constructor to use as the comparison? <\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\nPublic Class GenericCompare(Of T)\r\n    Implements System.Collections.Generic.IComparer(Of T)\r\n\r\n    Dim Func As Func(Of T, T, Integer)\r\n\r\n    Public Sub New(ByVal Func As Func(Of T, T, Integer))\r\n        Me.Func = Func\r\n    End Sub\r\n\r\n    Public Function Compare(ByVal x As T, ByVal y As T) As Integer Implements System.Collections.Generic.IComparer(Of T).Compare\r\n        Return Func(x, y)\r\n    End Function\r\n\r\nEnd Class\r\n\r\n<\/pre>\n<p>Assuming a general object to sort like this one:<\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\nPublic Class SomeObject\r\n\r\n    Public Property Name As String\r\n\r\n    Public Property Value1 As String\r\n\r\n    Public Property Value2 As String\r\n\r\nEnd Class\r\n\r\n<\/pre>\n<p>That will make our sort look like this:<\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\n        'Sort with custom compare\r\n        Items.Sort(New GenericCompare(Of SomeObject)(Function(x, y)\r\n                                                         If x.Name &gt; y.Name Then\r\n                                                             Return 1\r\n                                                         ElseIf x.Name &lt; y.Name Then\r\n                                                             Return -1\r\n                                                         Else\r\n                                                             Return 0\r\n                                                         End If\r\n                                                     End Function))\r\n\r\n<\/pre>\n<p>The above uses a long implementation for the comparison, which could be used for customizing the sort order or sorting on multiple fields if needed. If you just want a basic string comparison of one property, you can shorten the above to this:<\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\n        'Or, sort with default string compare, one liner\r\n        Items.Sort(New GenericCompare(Of SomeObject)(Function(x, y) String.Compare(x.Name, y.Name)))\r\n\r\n<\/pre>\n<p>Going crazy with this concept, you could even introduce an extension method to add another overload to <code>Sort()<\/code>.<\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\nPublic Module ExtensionMethods\r\n\r\n    &lt;System.Runtime.CompilerServices.Extension()&gt;\r\n    Public Sub Sort(Of T)(ByVal List As List(Of T), ByVal Func As Func(Of T, T, Integer))\r\n        List.Sort(New GenericCompare(Of T)(Func))\r\n    End Sub\r\n\r\nEnd Module\r\n\r\n<\/pre>\n<p>Then your sort becomes this:<\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\n        'Or with the extension method \r\n        Items.Sort(Function(x As SomeObject, y As SomeObject) String.Compare(x.Name, y.Name))\r\n\r\n<\/pre>\n<p>I&#8217;m not sure why exactly, but if you notice in this usage, I had to specify the type for the <code>x, y<\/code> arguments. Unlike the last example, the compiler isn&#8217;t able to infer the type of the arguments. <\/p>\n<p>Now, if you are looking at the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/3da4abas.aspx\">different overloads<\/a> for the <code>Sort<\/code> method, you may have notice that there is another overload that does basically what we just created.  <code>List(Of T).Sort(Comparison(Of T)<\/code> takes a delegate to a function. So in this usage you would just have to create a function in your code that follows the <code>Comparison(Of T)<\/code> delegate. As we know however, a lambda expression can be used anywhere a delegate is expected, so we can shorten this up into a one-liner as well. <\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\n        Items.Sort(New Comparison(Of SomeObject)(Function(x As SomeObject, y As SomeObject) String.Compare(x.Name, y.Name)))\r\n\r\n<\/pre>\n<p>Although, the <code>New Comparison(Of SomeObject)(...)<\/code> is actually not necessary, and the use of this override can be shortened to the equivalent of the extension method example above. <\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n\r\nItems.Sort(Function(x As SomeObject, y As SomeObject) String.Compare(x.Name, y.Name))\r\n\r\n<\/pre>\n<p>OK, so I played around a lot with the <code>List(Of T).Sort<\/code> methods and concluded that sorting a list of objects on an arbitrary property is pretty easy, and that .NET provides an overload that accepts a delegate or lambda for the comparison. So did I waste my time inventing that first method? Possibly, but I did prove to myself that you can create a generic class that can be made to accept lambdas that define its behavior. I can safely say I learned something and added another technique to the old toolbox, so in my onion a great use of time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;re like me, then you like to experiment with new and different ways to do the usual programming tasks that you do. Perhaps its just a reaction to the boredom of always doing things the same way. Sometimes its an attempt to make the easy but time consuming tasks faster. Often is in a&hellip;&nbsp;<a href=\"https:\/\/burnt-traces.com\/?p=104\" class=\"\" rel=\"bookmark\">Read More &raquo;<span class=\"screen-reader-text\">Lambda Expressions for Easy Custom Sorts<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[1,5],"tags":[15,19,24,88],"class_list":["post-104","post","type-post","status-publish","format-standard","hentry","category-uncategorized","category-vb-net","tag-generics","tag-lambda","tag-sort","tag-vb-net"],"_links":{"self":[{"href":"https:\/\/burnt-traces.com\/index.php?rest_route=\/wp\/v2\/posts\/104","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/burnt-traces.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/burnt-traces.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/burnt-traces.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/burnt-traces.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=104"}],"version-history":[{"count":1,"href":"https:\/\/burnt-traces.com\/index.php?rest_route=\/wp\/v2\/posts\/104\/revisions"}],"predecessor-version":[{"id":328,"href":"https:\/\/burnt-traces.com\/index.php?rest_route=\/wp\/v2\/posts\/104\/revisions\/328"}],"wp:attachment":[{"href":"https:\/\/burnt-traces.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=104"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/burnt-traces.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=104"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/burnt-traces.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=104"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}