Find in a List collection of objects

VBAHole22

Contributor
Joined
Oct 21, 2003
Messages
432
Location
VA
I have a class that has 4 properties, one of which is a string.
I make a collection of these class objects like so:
List<MyObject> myObjects = new List<MyObject>();

I then start throwing new objects in the collection:

Code:
MyObject m = new MyObject();
m.name  = "yatta";
m.id = 12;
m.isBig = true;
m.dbl = 12.5;
myObjects.Add(m);

My question is: how can I find out if there is already an object in the collection that has one of the properties at a specific value so I don't add it again?

For example if my next object had a name of "yatta" I would not want to add it again. But how can I find out if it is already in there?

I know that I can do the following but it seems clunky:
Code:
bool foundOne = false;
forech (MyObject i in myObjects)
{
if (i.name = m.name)
{
    foundOne = true;
}
}

There has to be a better way that I can do this where the code for it would be in my class and not in my program code.
 
The List<> object has a Contains() method that will tell you if an object is already in the list.

Alternatively a Dictionary<> might be more useful
C#:
Dictionary<string, MyObject> myObjects = new Dictionary<string, MyObject>();
MyObject m = new MyObject();
m.name = "yatta";
m.id = 12;
m.isBig = true;
m.dbl = 12.5;
myObjects.Add(m.name, m);
as this will easily allow you to check for a key value
C#:
if ( myObjects.ContainsKey("yatta"))
{
//key is present
}
 
I'll give that dictioinary a shot.

The problem with the Contains, as far as i can tell, is that it is comparing objects so if i make a new object there is no way its going to be 'equal' to an object in the collection already right?
The only way that the objects would be equal references would be if i pulled it out of there in the first place wouldn't it?
 
You could use the Exists method. Depending on exactly how you make use of it it can be pretty flexible. It accepts a delegate that determines if an object meets a condition, or a "predicate" (defined by you), and returns a boolean.

The example below shows one way to use it. Things could be made simpler with reflection, though. This is a class that implements methods to enable us to use the List<T>.Exists method:
C#:
// Define the class we want to compare. We will have two properties
// and two predicate methods that compare based on a property.
class SomeClass {
    
    // Define a property for the example
    string backingfield;
    public string SomeProperty{ 
        get{ return backingfield; } 
        set{ backingfield = value;} 
    }
    
    // define another example property
    string anotherbackingfield;
    public string AnotherProperty{ 
       get{ return anotherbackingfield; } 
       set{ anotherbackingfield = value; } 
    }
    
    // This is a predicate for SomeProperty
    public bool Predicate_4_SomeProperty(SomeObject comparison) {
        return comparison.SomeProperty == this.SomeProperty;
    }
    
    // This is a predicate for AnotherProperty
    public bool Predicate_4_AnotherProperty(SomeObject comparison) {
        return comparison.AnotherProperty == this.AnotherProperty;
    }
}
Note the predicate methods. They each define a condition that can be used for the Find, Exists, FindAll, Remove, etc. methods of a List<T> object. Predicate<T> is a generic delegate type that we can instantiate with our two predicate methods.

Below we actually use these predicates.
C#:
// Example code that uses our predicates
List<SomeObject> someObjects = new List<SomeObject>();

// Add items with unique "SomeProperty" values.
void AddToMyListIfSomePropertyIsUnique(SomeObject newItem) {
    if(someObjects.Exists(
        new Predicate<SomeObject>(newItem.Predicate_4_SomeProperty)))
    {
        someObjects.Add(newItem);
    }
}

// Add items with unique "AnotherProperty" values.
void AddToMyListIfAnotherPropertyIsUnique(SomeObject newItem) {
    if(someObjects.Exists(
        new Predicate<SomeObject>(newItem.Predicate_4_AnotherProperty)))
    {
        someObjects.Add(newItem);
    }
}
Hope that helps. Again, reflection could come in handy here. You could write a class that can create a predicate for any property of any object using reflection.
 
KeyedCollection Generic Class

Code:
using System.Collections.ObjectModel;

public class MyObjectNameKeyedCollection : KeyedCollection<string,MyObject> 
{
	protected override string GetKeyForItem(MyObject item)
	{
		if (item==null)
		{
			throw new ArgumenNullException("item","item is null");
		}
		if (item.name==null)
		{
			throw new ArgumentException("item name is null","item")
		}
		if (item.name.Length==0)
		{
			throw new ArgumentException("item name is empty","item");
		}
		return item.name
	}
}
 
Back
Top