<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Making Use of the Find, FindIndex or FindAll Methods With Generic Lists in C#</title>
	<atom:link href="http://www.del337ed.com/blog/index.php/2008/01/24/making-use-of-the-find-findindex-or-findall-methods-with-generic-lists-in-c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.del337ed.com/blog/index.php/2008/01/24/making-use-of-the-find-findindex-or-findall-methods-with-generic-lists-in-c/</link>
	<description>Mostly tech talk</description>
	<lastBuildDate>Tue, 10 Aug 2010 10:51:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Kevin P. Rice</title>
		<link>http://www.del337ed.com/blog/index.php/2008/01/24/making-use-of-the-find-findindex-or-findall-methods-with-generic-lists-in-c/comment-page-1/#comment-702</link>
		<dc:creator>Kevin P. Rice</dc:creator>
		<pubDate>Tue, 25 Aug 2009 03:35:05 +0000</pubDate>
		<guid isPermaLink="false">http://www.del337ed.com/blog/index.php/2008/01/24/making-use-of-the-find-findindex-or-findall-methods-with-generic-lists-in-c/#comment-702</guid>
		<description>NOW, after learning a bit more, let&#039;s see if we can improve your code further:

(1) Here, I utilize the List.Contains() method to eliminate the inner nested Find():

    private void validateUserInput(List listWithValuesEnteredByUser) 
    {
      List asiaList = MethodThatReturnsAllCountriesInAsia();

      if (string.IsNullOrEmpty(
        listWithValuesEnteredByUser.Find(current =&gt; !asiaList.Contains(current)))) {
        // country not found, user input found to be invalid
      }
    }


NOW, LET&#039;S GO FOR SOME ONE-LINERS!!!

(2) We can simply return all INVALID input strings (by changing the return type of the function):

    private List validateUserInput(List listWithValuesEnteredByUser) 
    {
      return listWithValuesEnteredByUser.FindAll(current =&gt;
         !MethodThatReturnsAllCountriesInAsia().Contains(current));
    }


(3) Or, return true if all user input is valid (return type changed to bool):

    private bool validateUserInput(List listWithValuesEnteredByUser) 
    {
      return listWithValuesEnteredByUser.FindAll(current =&gt; 
        !MethodThatReturnsAllCountriesInAsia().Contains(current)).Count == 0;
    }


Well, I learned a lot! Thanks for the article that gave me something to play with!

Kevin
San Luis Obispo CA</description>
		<content:encoded><![CDATA[<p>NOW, after learning a bit more, let&#8217;s see if we can improve your code further:</p>
<p>(1) Here, I utilize the List.Contains() method to eliminate the inner nested Find():</p>
<p>    private void validateUserInput(List listWithValuesEnteredByUser)<br />
    {<br />
      List asiaList = MethodThatReturnsAllCountriesInAsia();</p>
<p>      if (string.IsNullOrEmpty(<br />
        listWithValuesEnteredByUser.Find(current =&gt; !asiaList.Contains(current)))) {<br />
        // country not found, user input found to be invalid<br />
      }<br />
    }</p>
<p>NOW, LET&#8217;S GO FOR SOME ONE-LINERS!!!</p>
<p>(2) We can simply return all INVALID input strings (by changing the return type of the function):</p>
<p>    private List validateUserInput(List listWithValuesEnteredByUser)<br />
    {<br />
      return listWithValuesEnteredByUser.FindAll(current =&gt;<br />
         !MethodThatReturnsAllCountriesInAsia().Contains(current));<br />
    }</p>
<p>(3) Or, return true if all user input is valid (return type changed to bool):</p>
<p>    private bool validateUserInput(List listWithValuesEnteredByUser)<br />
    {<br />
      return listWithValuesEnteredByUser.FindAll(current =&gt;<br />
        !MethodThatReturnsAllCountriesInAsia().Contains(current)).Count == 0;<br />
    }</p>
<p>Well, I learned a lot! Thanks for the article that gave me something to play with!</p>
<p>Kevin<br />
San Luis Obispo CA</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin P. Rice</title>
		<link>http://www.del337ed.com/blog/index.php/2008/01/24/making-use-of-the-find-findindex-or-findall-methods-with-generic-lists-in-c/comment-page-1/#comment-701</link>
		<dc:creator>Kevin P. Rice</dc:creator>
		<pubDate>Tue, 25 Aug 2009 03:12:01 +0000</pubDate>
		<guid isPermaLink="false">http://www.del337ed.com/blog/index.php/2008/01/24/making-use-of-the-find-findindex-or-findall-methods-with-generic-lists-in-c/#comment-701</guid>
		<description>Good work! I&#039;m just learning this stuff too. I noticed that you MISSED OUT on a couple good opportunities in your code---

(1) The outer foreach loop presents an opportunity to use the List.ForEach() method that is IDENTICAL in use to the List.Find() method. Thus, your solution now has NESTED anonymous delegates and becomes:

      listWithValuesEnteredByUser.ForEach(delegate(string current) {
        if (string.IsNullOrEmpty(asiaList.Find(delegate(string input) {
          return input == current;
        }
          ))) {
          // country not found, user input found to be invalid
        }
      });


(2) Anonymous delegate functions are good--lambda expressions/statements can be better! I&#039;ll leave it for you to read up on lambda expressions, however, suffice it to say, an anonymous delegate function in the form of &quot;delegate(string val) { return val == x; }&quot; is IDENTICAL TO the lambda expression &quot;val =&gt; val == x&quot;. With lambda expressions you don&#039;t have to re-state the redundant information (&#039;delegate&#039;, &#039;string&#039;, &#039;return&#039;). Your &#039;if&#039; function now becomes simply:

        if (string.IsNullOrEmpty(asiaList.Find(input =&gt; input == current))) { }

This code is IDENTICAL to yours.

(3) In addition to functions, lambda notation can also be used define a statement block (C# only as of VS2008). Thus, in my section (1) above, you can likewise get rid of the first anonymous delegate function.

Hence, the IDENTICAL CODE to yours, re-written using ForEach() and lambda notation is now:

      listWithValuesEnteredByUser.ForEach(current =&gt; {
        if (string.IsNullOrEmpty(asiaList.Find(input =&gt; input == current))) {
          // country not found, user input found to be invalid
        }
      });

Using lambda notation, think of the variable name on the left side of the =&gt; as the parameter of your delegate function (because it actually is just notation for the exact same thing):

&quot;parameter =&gt;&quot; replaces &quot;delegate(type parameter)&quot;

You don&#039;t have to specify &quot;delegate&quot; or the type (string, in your case) because it is already inferred from the type of the List collection. This reduces typing!

On the right side of the =&gt; notation, you can specify a simple expression whose value is returned or a statement block.... depending on what is called for:

(1) The List.Find() method expects a &quot;Predicate&quot;. Webster&#039;s dictionary says a predicate (n.) is &quot;a propositional function of one or more arguments. The predicate you are using is &quot;return input == current;&quot;. Thus, the propositional function (predicate) is &quot;is &#039;input&#039; equal to &#039;current&#039;?&quot;. The bool result is the return value. Think of &quot;Predicate&quot; as a filter. Your predicate function defines and filters what Find() is looking for.

(2) The List.ForEach() method expects an &quot;Action&quot; delegate (defined in the System namespace). The Action(T) delegate &quot;Encapsulates a method that takes a single parameter and does not return a value.&quot; Thus, notice my use of a statement block &quot;{...}&quot; to the right side of the =&gt; lambda notation. This entire statement block is executed &quot;ForEach&quot; value in the collection, with &quot;current&quot; as the parameter of the function.

A simplification that may help you understand the List.ForEach() method and &quot;Action&quot; delegate is this line of code which writes all user entered values to the console:

      listWithValuesEnteredByUser.ForEach(value =&gt; Console.WriteLine(value));


CONCLUSION:
Don&#039;t forget what you know about delegates and anonymous delegate functions! Lambda notation is not something different! It&#039;s just an easier way to write the exact same thing.</description>
		<content:encoded><![CDATA[<p>Good work! I&#8217;m just learning this stuff too. I noticed that you MISSED OUT on a couple good opportunities in your code&#8212;</p>
<p>(1) The outer foreach loop presents an opportunity to use the List.ForEach() method that is IDENTICAL in use to the List.Find() method. Thus, your solution now has NESTED anonymous delegates and becomes:</p>
<p>      listWithValuesEnteredByUser.ForEach(delegate(string current) {<br />
        if (string.IsNullOrEmpty(asiaList.Find(delegate(string input) {<br />
          return input == current;<br />
        }<br />
          ))) {<br />
          // country not found, user input found to be invalid<br />
        }<br />
      });</p>
<p>(2) Anonymous delegate functions are good&#8211;lambda expressions/statements can be better! I&#8217;ll leave it for you to read up on lambda expressions, however, suffice it to say, an anonymous delegate function in the form of &#8220;delegate(string val) { return val == x; }&#8221; is IDENTICAL TO the lambda expression &#8220;val =&gt; val == x&#8221;. With lambda expressions you don&#8217;t have to re-state the redundant information (&#8216;delegate&#8217;, &#8217;string&#8217;, &#8216;return&#8217;). Your &#8216;if&#8217; function now becomes simply:</p>
<p>        if (string.IsNullOrEmpty(asiaList.Find(input =&gt; input == current))) { }</p>
<p>This code is IDENTICAL to yours.</p>
<p>(3) In addition to functions, lambda notation can also be used define a statement block (C# only as of VS2008). Thus, in my section (1) above, you can likewise get rid of the first anonymous delegate function.</p>
<p>Hence, the IDENTICAL CODE to yours, re-written using ForEach() and lambda notation is now:</p>
<p>      listWithValuesEnteredByUser.ForEach(current =&gt; {<br />
        if (string.IsNullOrEmpty(asiaList.Find(input =&gt; input == current))) {<br />
          // country not found, user input found to be invalid<br />
        }<br />
      });</p>
<p>Using lambda notation, think of the variable name on the left side of the =&gt; as the parameter of your delegate function (because it actually is just notation for the exact same thing):</p>
<p>&#8220;parameter =&gt;&#8221; replaces &#8220;delegate(type parameter)&#8221;</p>
<p>You don&#8217;t have to specify &#8220;delegate&#8221; or the type (string, in your case) because it is already inferred from the type of the List collection. This reduces typing!</p>
<p>On the right side of the =&gt; notation, you can specify a simple expression whose value is returned or a statement block&#8230;. depending on what is called for:</p>
<p>(1) The List.Find() method expects a &#8220;Predicate&#8221;. Webster&#8217;s dictionary says a predicate (n.) is &#8220;a propositional function of one or more arguments. The predicate you are using is &#8220;return input == current;&#8221;. Thus, the propositional function (predicate) is &#8220;is &#8216;input&#8217; equal to &#8216;current&#8217;?&#8221;. The bool result is the return value. Think of &#8220;Predicate&#8221; as a filter. Your predicate function defines and filters what Find() is looking for.</p>
<p>(2) The List.ForEach() method expects an &#8220;Action&#8221; delegate (defined in the System namespace). The Action(T) delegate &#8220;Encapsulates a method that takes a single parameter and does not return a value.&#8221; Thus, notice my use of a statement block &#8220;{&#8230;}&#8221; to the right side of the =&gt; lambda notation. This entire statement block is executed &#8220;ForEach&#8221; value in the collection, with &#8220;current&#8221; as the parameter of the function.</p>
<p>A simplification that may help you understand the List.ForEach() method and &#8220;Action&#8221; delegate is this line of code which writes all user entered values to the console:</p>
<p>      listWithValuesEnteredByUser.ForEach(value =&gt; Console.WriteLine(value));</p>
<p>CONCLUSION:<br />
Don&#8217;t forget what you know about delegates and anonymous delegate functions! Lambda notation is not something different! It&#8217;s just an easier way to write the exact same thing.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
