CSharp/C# >> Possible to make Array.Find Predicate match method more universal? To take multiple parameters?

by Jon Skeet [C# MVP] » Sat, 30 Aug 2008 02:15:58 GMT

raylopez99 < XXXX@XXXXX.COM > wrote:
> On Aug 22, 12:54爌m, G鰎an Andersson < XXXX@XXXXX.COM > wrote:
> >
> > Create an instance of the class passing the R2 value, and use it's method:
> >
> > first = Array.Find<Point>(points, new ProductGT10Comparer(R2).ProductGT10);
> >
> > Another alternative is to use an anonymous method. Then the delegate
> > will contain the value of R2 so that the code can use it (so it's pretty
> > much the same as storing the R2 value in a class instance):
> >
> > first = Array.Find<Point>(points, delegate(Point p) { return
> > R2.Contains(p); });
> >
>
> Thanks Goran! I understood the first example, but not the 'anonymous
> delegate' example (I'm not used to that format, but it looks
> compact). In any event, I appreciate your answer, it's a nice trick
> that I'll store in my library, and I'll report back if I have any
> problems.

This is basically the point behind closures - they allow you to carry
around some of your environment (including local variables) within
delegates. See
http://csharpindepth.com/Articles/Chapter5/Closures.aspx for other
examples.

--
Jon Skeet - < XXXX@XXXXX.COM >
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

Similar Threads

1. Possible to make Array.Find Predicate match method more universal? To take multiple parameters?

I suspect the answer to this question is that it's impossible, but how
do I make the below code work, at the point where it breaks (marked
below).  See error CS0411

This is the complete code.  Copy and paste it into VS2008 for a
Windows Forms application.

With some effort I can do the job with a user defined function, but my
question is whether I can do it using the built in library function
"Array.Find" and a predicate that takes multiple parameters rather
than one.

Thanks

RL

//////////////
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Forms01
{
    public partial class Form1 : Form
    {

        Point[] points;

        public Form1()
        {
            points = new Point[]{ new Point(100, 200),
            new Point(150, 250), new Point(250, 375),
            new Point(275, 395), new Point(295, 450) };

            InitializeComponent();

        }



private void button1_Click(object sender, EventArgs e)
{

    Point first = new Point(11,11);

    try
    {
        first = Array.Find(points, ProductGT10);
        MessageBox.Show("Point is: " + first.X.ToString());
    }
    catch (ArgumentNullException)
    {
        MessageBox.Show("null");
    }

// this first try block works, as expected, when commenting out the
second try block below,
// to give output 慞oint is: 150?


    Rectangle R2 = new Rectangle(100, 100, 200, 200);
    Point second = new Point(12, 12);

//second try block does not work (does not compile)


    try
    {
        first = Array.Find(points, ProductGT10_2(second, R2));

/*
//error CS0411: The type arguments for method
'System.Array.Find<T>(T[], System.Predicate<T>)' cannot be inferred
from the usage. Try specifying the type arguments explicitly

*/

        MessageBox.Show("Point2 is: " + second.X.ToString());
    }
    catch (ArgumentNullException)
    {
        MessageBox.Show("null2");
    }



}


///////////////////
        private static bool ProductGT10(Point p)
    {

        Rectangle R = new Rectangle(101, 101, 200, 200);

//hard code the rectangle R
//can we avoid having to hard code the rectangle here?  Can we pass
it?  See below

                if (R.Contains(p))
                {
                    return true;
                }
                else
                {
                    return false;
                }
    }

//this doesn't compile
        private static bool ProductGT10_2(Point P, Rectangle R) //
passing the R
        {
            if (R.Contains(P))
            {
                return true;
            }
            else
            {
                return false;
            }
        }


}//end of Form1

} //end of Forms01 namespace



2. Possible to make Array.Find Predicate match method more universal? To take multiple parameters? - CSharp/C#

3. Partial specialisation of method taking parameterized parameter

I'd like to create a partial specialization of a member-method of a
parameterized class which takes a parameterized argument, but I'm not
sure if it's possible or, if possible, how. The following code
demonstrates what I'd like to to:

#include <iostream>

template<class T>
struct BarA
{
	void bar() { std::cout << "BarA\n"; }
};

template<class T>
struct BarB
{
	void bar() { std::cout << "BarB\n"; }
};

template<class T>
struct Test
{
        template<template<class U = T> class V>
		void foo(V<T>& f);
};

template<class T>
template<template<class> class V>
void Test<T>::foo(V<T>& f)
{
	f.bar();

}

/* A partial specialization that prepends the output of f.bar() with
"BarB: "
template<class T>
template<>
void Test<T>::foo(BarB<T> f)
{
	std::cout "BarB: ";
	f.bar();
}
*/

int main()
{
	BarA<int> a;
	BarB<int> b;

	Test<int> t;
	t.foo(a);
	t.foo(b);
}

This should, print:
BarA
BarB: BarB

Any help appreciated.

Erik Wikstr

4. web method with parameter and return of same type makes a by ref parameter

5. Template parameter matching for class and class method

6. This delegate takes ParameterizedThreadStart takes an object but can be called wirhout parameter - CSharp/C#

7. string literal does not match array template parameter

The purpose of the following code is to search a string for
a substring, and replace the first character of the found string
with a new value:

  #include <algorithm>
  #include <string>

  template<typename InIt, typename CharT, int N>
  void filter(InIt begin, InIt end, CharT const (&needle)[N], CharT
new_ch)
  {
    while (end != (begin = std::search(begin, end, needle, needle + N -
1)))
      *begin++ = new_ch;
  }

  int main()
  {
    std::string s("bar");
    filter(s.begin(), s.end(), "hi", 'H');
  }

On GCC 3.4.1 it compiles correctly, but on BCC 5.5.1 I get the
error:

   Could not find a match for filter<InIt,CharT,N>
     (char *, char *, char *, char)

Is BCC wrong?

8. How to implement a Predicate in 'find' algorithm for finding a