views:

158

answers:

3

I have a collection of Contacts that inherits from CollectionBase:

public class ContactCollection : CollectionBase{
    //...
}

each contact in the collection has a unique ID:

public class Contact{
    public int ContactID{
        get;
        private set;
    }
    //...
}

I think what I would like to do is something like the following:

// get the contact by their unique [Contact]ID
Contact myPerson = Contact.GetContactById(15);

// get all contacts for the customer
ContactCollection contacts = customer.GetContacts();

// replaces the contact in the collection with the 
// myPerson contact with the same ContactID.
contacts.ReplaceAt(myPerson);

// saves the changes to the contacts and the customer
// customer.Save();

There is probably a better way...if so, please suggest it.

+3  A: 
Contact contact = Contact.GetContactById(15);
ContactCollection contacts = customer.GetContacts();
contacts[contacts.IndexOf(contacts.Find(c => c.Id == contact.Id))] = contact;

This is a bit better...

int id = 15;
ContactCollection contacts = customer.GetContacts();
int index = users.FindIndex(c => c.Id == id)
if (index >= 0) contacts[index] = Contact.GetContactById(id);
hunter
+1 fro LINQ ...
please, do tell. I've got C# 3.5 at my disposal. (someone gave you a -1 for your suggestion, WTF?) +1
David Murdoch
@David - I suspect (as it wasn't me) that the -1 was for making the suggestion without either providing a link(!) or example.
ChrisF
The -1 most likely came from the fact that "If you're using LINQ then this is simple" was a very bare answer that didn't solve anything on its own. You were even asking for clarification yourself.
ccomet
yeah, I was still editing
hunter
+6  A: 

For starters I would change out CollectionBase and use List<T>. CollectionBase was a 1.0 addition that is no longer needed because of Generics. Actually, you might not even need your ContactCollection class, as most of the methods you'll probably need will already be implemented in the generics implementation.

Then you can use LINQ:

var item = Collection.FirstOrDefault(x => x.Id == 15);

And if you want to keep these, then you can have your ContactCollection class just be a wrapper for the List<T> Then the code you actually have to write will be minimal as the generic will do most of the work.

Contact myPerson = Contact.GetContactById(15);

// get all contacts for the customer
ContactCollection contacts = customer.GetContacts();

// replaces the contact in the collection with the 
// myPerson contact with the same ContactID.
contacts.ReplaceAt(myPerson);

// saves the changes to the contacts and the customer
// customer.Save();
Kevin
should be "`==`"?
David Murdoch
+1 for addressing the serious architecture concerns displayed
Chris Marisic
@David Thanks, I missed that.
Kevin
woah, I just crashed IIS. hm.
David Murdoch
@David if you want to post your code, we can see if we can quickly spot the problem.
Kevin
I had replaced `CollectionBase` with `List<Contact>` and left the methods (`Index`, `IndexOf`, `Add`, `CopyTo`, etc.).
David Murdoch
@Kevin, how does this replace that item again?
hunter
Accepted. I'm using `public class ContactCollection : List<Contact>` and `Collection.FirstOrDefault(x => x.Id == 15)`. Thanks!
David Murdoch
+1  A: 

Why not remove the inheritance from CollectionBase, and rely on a composited Dictionary?

That way, retrieving by unique ID is close to an O(1) operation, i.e. very fast, compared to linear search over a List.

If each Contact also has a List of ContactIDs, then retrieving them from the Contacts Dictionary is also easy to do.

Some more information about Dictionaries can be found at : http://dotnetperls.com/dictionary-keys

Jean Azzopardi
contacts won't have contacts and the most contacts a customer will have is around 10 with an average of 3...so speed won't be an issue here. +1
David Murdoch