Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

help on generic space

5 views
Skip to first unread message

GS

unread,
Jun 19, 2009, 1:40:02 AM6/19/09
to

I only dabble in C# once in a long while and am I lost. I got problem with
the following code
How should I reconcile
Color c2 = colors.Find(c1)
so I don't get
Error 1 The best overloaded method match for
'System.Collections.Generic.List<System.Drawing.Color>.Find(System.Predicate
<System.Drawing.Color>)' has some invalid arguments

===================
List<Color> colors = new List<Color>(256);
Color c1, c2;
int i, j, nc = 0, ih = bmp.Height, iw = bmp.Width;
const int IMax = 32;
for (i = 0; i < Math.Min(iw, IMax); i++)
{
//find number of colors
for (j = 0; j < Math.Min(ih,IMax); j++)
{
c1 = bmp.GetPixel(i, j);
if (i == 0 & j == 0)
{
colors.Add(c1);
}
else
{
c2 = colors.Find(c1);
if (c2 == null)
{
colors.Add(c1);
if (nc > 256)
{
MessageBox.Show("Warning - input image has
more than 256 colors and maybe rejected by Visual Studio as application
icon");
return false;
}
else nc++;
}
}
}
}
return true;


Alberto Poblacion

unread,
Jun 19, 2009, 3:05:10 AM6/19/09
to
"GS" <gsmsnews.mic...@msnews.Nomail.com> wrote in message
news:uhIGmBK8...@TK2MSFTNGP04.phx.gbl...

>
> I only dabble in C# once in a long while and am I lost. I got problem with
> the following code
> How should I reconcile
> Color c2 = colors.Find(c1)
> so I don't get
> Error 1 The best overloaded method match for
> 'System.Collections.Generic.List<System.Drawing.Color>.Find(System.Predicate
> <System.Drawing.Color>)' has some invalid arguments

The error message itself tells you what the argument to "Find" should
be: it is expecting a Predicate<Color>, which means "a delegate to a
function that takes a Color and returns a Boolean". You can provide such a
delegate by means of a Lambda:

Color c2 = colors.Find(c=>c==c1);

Peter Duniho

unread,
Jun 19, 2009, 4:51:57 AM6/19/09
to
On Thu, 18 Jun 2009 22:40:02 -0700, GS
<gsmsnews.mic...@msnews.nomail.com> wrote:

>
> I only dabble in C# once in a long while and am I lost. I got problem
> with
> the following code
> How should I reconcile
> Color c2 = colors.Find(c1)
> so I don't get
> Error 1 The best overloaded method match for
> 'System.Collections.Generic.List<System.Drawing.Color>.Find(System.Predicate
> <System.Drawing.Color>)' has some invalid arguments

In addition to what Alberto wrote...

For a simple lookup like that, you can also use the IndexOf() method. In
fact, in the code you posted, that's probably preferable. The code you
posted has a bug, in which your code will think it has always found the
desired color, because Color is a value type, and so if the Color value
you're looking for isn't found, the default Color value will be returned,
not "null".

Also because Color is a value type, obviously you don't need the actual
instance you're looking for. You just need to know the value exists in
your list. The IndexOf() method will return an index, -1 if the value
isn't found.

And yet another alternative would be the Exists() method. Like the Find()
method, it takes a Predicate<T>, but rather than returning the element
that was found, it simply returns a boolean indicating whether the value
is in the list or not. Again, this seems much more appropriate given your
usage.

I'd like to suggest that you abandon the List<T> class altogether. Even
though the list will never have more than 257 (*) elements, as it gets
larger the searches done at each pixel will get more and more expensive,
hurting performance significantly.

(*) (256, if you switch the "add, then check count" around so that it's
"check count, then add" instead...and if you do that, you avoid that last
reallocation of the List<T> buffer when you exceed the maximum allowed
number of colors :) )

Normally I argue against worrying about optimizations early in
development, but in this case there's such a high chance of the linear
search being prohibitive, I think you will probably want to use a faster
data structure. You can use HashSet<Color> instead of List<Color>. You
can use the Contains() method to check whether the set actually contains
the color you're looking for.

I'd also recommend getting rid of your special-case for the first pixel
("if (i == 0 & j == 0)"). Not only should you be using the "&&" operator
instead of the "&" operator, it's superfluous anyway and just detracts
from the readability of the code. Just call HashSet.Contains() for the
first pixel just like you do for every other one; it'll be practically as
fast and will keep the code more general.

Finally, I'll point out that you can also get rid of the "nc" counter.
Even List<T> has a Count property, and the HashSet<T> class does too.
Just check the Count property instead of keeping the counter.

In the end, this is what the code would look like if I had my way (well,
structurally anyway):

HashSet<Color> colors = new HashSet<Color>();
int iMax = Math.Min(bmp.Width, 32), jMax = Math.Min(bmp.Height, 32);

for (int i = 0; i < iMax; i++)
{
for (int j = 0; j < jMax; j++)
{
Color color = bmp.GetPixel(i, j);

if (!colors.Contains(color))
{
if (colors.Count == 256)
{
// This is a utility method...make the caller display
// the message box if it fails
return false;
}

colors.Add(color);
}
}
}

Pete

Ben Voigt [C++ MVP]

unread,
Jun 19, 2009, 6:01:40 PM6/19/09
to

Or you could just use the right method. IndexOf is what most people want
when Find isn't working, for this particular case Contains would solve the
problem better. But using a better container, like a Set, would be even
better.


GS

unread,
Jun 19, 2009, 7:29:11 PM6/19/09
to
thx. I took up your suggestion and replace c2 with into int c1Idx and then
compare to less than 1. worked like a charm..

thank you again.


I must be too tired not able to think clearly.

I am somewhat better after some extra sleep although still not quite enough
quality sleep

"Ben Voigt [C++ MVP]" <bvo...@newsgroup.nospam> wrote in message
news:%23MxEHmS...@TK2MSFTNGP02.phx.gbl...

Jeff Johnson

unread,
Jun 26, 2009, 1:44:56 PM6/26/09
to

"Ben Voigt [C++ MVP]" <bvo...@newsgroup.nospam> wrote in message
news:%23MxEHmS...@TK2MSFTNGP02.phx.gbl...

> But using a better container, like a Set, would be even better.

What is this "Set" of which you speak? The only thing I found in MSDN was a
C++ STL thing.


Ben Voigt [C++ MVP]

unread,
Jul 2, 2009, 10:05:03 AM7/2/09
to

e.g. http://www.codeplex.com/PowerCollections

I thought .NET had added a set class.... apparently it's still in beta:
http://msdn.microsoft.com/en-us/library/bb397727(VS.100).aspx


Peter Duniho

unread,
Jul 2, 2009, 1:07:43 PM7/2/09
to

No, the docs are still in beta. HashSet<T> has been in there since 3.5.

I actually posted a detailed reply to the OP when his question first
appeared, including describing HashSet<T> as a possible solution (with
code example). But, given recent problems with my posts being blocked by
Microsoft's servers, it's possible no one else saw the post:

http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/958a199d179b08d9

Pete

0 new messages