473,888 Members | 2,194 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Creating IndexOf in a custom collection

I have a design question. I am creating a custom collection of products.
The unique key for the products is productId which is an integer.

By default, IndexOf(object obj), when obj is an int, would return the value
of obj because it returns the index of the item at position obj.

Thoughts I had were to let the default method perform the default behavior
and then create an overload as IndexOf(int index, ProductSearchCr iteria
criteria) where ProductSearchCr iteria is an enum with { Index, ProductId }
allowing the developer calling my class to specify the meaning of the int
when calling IndexOf().

I'd appreciate any feedback and especially any better ideas.

Thanks,

Dale

--
Dale Preston
MCAD C#
MCSE, MCDBA
Nov 2 '06 #1
7 5531
Hang on...

what exactly does "IndexOf(5, blah.Index)" mean? Give me the index of the
item at index 5 [position 6]?

Do you perhaps mean the /indexer/ (this), i.e. this[5]? In which case, I
would suggest keeing the int indexer with it's general usage for
collections, and perhaps add a GetByProductID( int id), or (more generic) a
GetByKey.

In some cases, a key indexer is common (e.g. hashtable, etc), but you get
into a lot of trouble if both the key and index share a type... or are
implicitely convertible. Lots of pain.

Marc
Nov 2 '06 #2
IndexOf(5, blah.Index) means return the index of the object at position 5.
This basically mimics the default behavior and, in fact, this overload would
simply call the default overload. The real usefulness of this and the
default behavior is to return -1 if there is no position 5.

IndexOf(5, blah.ProductId) means return the index of the product whose
ProductId is 5.

I agree with you about the problems when the key is integer. I even thought
about doing away with the default behavior because consumers of my class
would probably never call it - after all, you can always do
ProductCollecti on.Count to see if there is a position 5 - but many other
collection methods depend on the default implementation of IndexOf and all of
those methods would have to be rewritten as well.

Unless someone else comes up with something neither of us thought of, I am
going to go with your suggestion. It seems to be the right thing to do:
leave the default behavior alone and create a new GetIndexById() method.

Thanks,

Dale
--
Dale Preston
MCAD C#
MCSE, MCDBA
"Marc Gravell" wrote:
Hang on...

what exactly does "IndexOf(5, blah.Index)" mean? Give me the index of the
item at index 5 [position 6]?

Do you perhaps mean the /indexer/ (this), i.e. this[5]? In which case, I
would suggest keeing the int indexer with it's general usage for
collections, and perhaps add a GetByProductID( int id), or (more generic) a
GetByKey.

In some cases, a key indexer is common (e.g. hashtable, etc), but you get
into a lot of trouble if both the key and index share a type... or are
implicitely convertible. Lots of pain.

Marc
Nov 2 '06 #3
You may have misundertood the default implementation; normally, you give
IndexOf an actual item (hence object, not the index), and it tells you the
index of the first item to Equals() it. The only time IndexOf(5) would be
useful is if your collection held integers... and it would only work if 5
was in the list.

I'm assuming you are dealing with 1.1; for completeness in terms of naming /
consistency, you might also like to compare this to the
List<T>.FindInd ex(Predicate<T> ) method in 2.0.

Marc
Nov 2 '06 #4
Dale,

The best way of doing this is to use predicate logic. Which framework
version are you using? The reason I'm asking is because this is much
easier in 2.0. Consider the following example.

// This method would be in your custom collection.
public int FindIndex(Predi cate<Tmatch)
{
for (int index = 0; index < collection.Coun t; index++)
{
if (match(collecti on[index])) return index;
}
return -1;
}

// This is how you would use it.
public static void Main()
{
YourCollection collection = GetReferenceToY ourCollectionSo mehow();

int index1 = collection.Find Index(
delegate(YourIt em item)
{
return item.Index == 5;
});

int index2 = collection.Find Index(
delegate(YourIt em item)
{
return item.ProductId == 5;
});
}

You can use the List<Tcollectio n as an example. It already has the
FindIndex method. You can do something similar in 1.1, but you'd have
to define your own strongly-typed delegate and provide an
implementation for each type of search you want to perform (by Index,
ProductId, etc).

Brian

Dale wrote:
IndexOf(5, blah.Index) means return the index of the object at position 5.
This basically mimics the default behavior and, in fact, this overload would
simply call the default overload. The real usefulness of this and the
default behavior is to return -1 if there is no position 5.

IndexOf(5, blah.ProductId) means return the index of the product whose
ProductId is 5.

I agree with you about the problems when the key is integer. I even thought
about doing away with the default behavior because consumers of my class
would probably never call it - after all, you can always do
ProductCollecti on.Count to see if there is a position 5 - but many other
collection methods depend on the default implementation of IndexOf and all of
those methods would have to be rewritten as well.

Unless someone else comes up with something neither of us thought of, I am
going to go with your suggestion. It seems to be the right thing to do:
leave the default behavior alone and create a new GetIndexById() method.

Thanks,

Dale
--
Dale Preston
MCAD C#
MCSE, MCDBA
"Marc Gravell" wrote:
Hang on...

what exactly does "IndexOf(5, blah.Index)" mean? Give me the index of the
item at index 5 [position 6]?

Do you perhaps mean the /indexer/ (this), i.e. this[5]? In which case, I
would suggest keeing the int indexer with it's general usage for
collections, and perhaps add a GetByProductID( int id), or (more generic) a
GetByKey.

In some cases, a key indexer is common (e.g. hashtable, etc), but you get
into a lot of trouble if both the key and index share a type... or are
implicitely convertible. Lots of pain.

Marc

Nov 2 '06 #5
Of course, if product id is unique (original post) you could also look at
Dictionary<int, YourClass(2.0) or Hashtable (1.1); this doesn't guarantee
the rigid insertion order, but makes for very efficient lookup by ID, and
would still support enumeration.

Marc
Nov 2 '06 #6
Well, this is getting more interesting than I'd hoped. Here's a little more
information.

I have long been a fan of custom collections over arrays. This app is in
..Net 2.0. I started out with a custom collection by extending
System.Collecti ons.Generics.IE numerable. But because I want to have indexers
based on specific properties of the contained class, my Generics based
collection needs to be locked into the Product type. To do that, I add
"where T : Product".

Suddenly my Generic class is no longer Generic and the whole generic
structure of having to specify <Productseems like a burden with no benefit.

Am I wrong? I'd love to use the new features of .Net 2.0 where they fit but
does it always fit? Or does it fit here?

Thanks for your patience,

Dale
--
Dale Preston
MCAD C#
MCSE, MCDBA
"Brian Gideon" wrote:
Dale,

The best way of doing this is to use predicate logic. Which framework
version are you using? The reason I'm asking is because this is much
easier in 2.0. Consider the following example.

// This method would be in your custom collection.
public int FindIndex(Predi cate<Tmatch)
{
for (int index = 0; index < collection.Coun t; index++)
{
if (match(collecti on[index])) return index;
}
return -1;
}

// This is how you would use it.
public static void Main()
{
YourCollection collection = GetReferenceToY ourCollectionSo mehow();

int index1 = collection.Find Index(
delegate(YourIt em item)
{
return item.Index == 5;
});

int index2 = collection.Find Index(
delegate(YourIt em item)
{
return item.ProductId == 5;
});
}

You can use the List<Tcollectio n as an example. It already has the
FindIndex method. You can do something similar in 1.1, but you'd have
to define your own strongly-typed delegate and provide an
implementation for each type of search you want to perform (by Index,
ProductId, etc).

Brian

Dale wrote:
IndexOf(5, blah.Index) means return the index of the object at position 5.
This basically mimics the default behavior and, in fact, this overload would
simply call the default overload. The real usefulness of this and the
default behavior is to return -1 if there is no position 5.

IndexOf(5, blah.ProductId) means return the index of the product whose
ProductId is 5.

I agree with you about the problems when the key is integer. I even thought
about doing away with the default behavior because consumers of my class
would probably never call it - after all, you can always do
ProductCollecti on.Count to see if there is a position 5 - but many other
collection methods depend on the default implementation of IndexOf and all of
those methods would have to be rewritten as well.

Unless someone else comes up with something neither of us thought of, I am
going to go with your suggestion. It seems to be the right thing to do:
leave the default behavior alone and create a new GetIndexById() method.

Thanks,

Dale
--
Dale Preston
MCAD C#
MCSE, MCDBA
"Marc Gravell" wrote:
Hang on...
>
what exactly does "IndexOf(5, blah.Index)" mean? Give me the index of the
item at index 5 [position 6]?
>
Do you perhaps mean the /indexer/ (this), i.e. this[5]? In which case, I
would suggest keeing the int indexer with it's general usage for
collections, and perhaps add a GetByProductID( int id), or (more generic) a
GetByKey.
>
In some cases, a key indexer is common (e.g. hashtable, etc), but you get
into a lot of trouble if both the key and index share a type... or are
implicitely convertible. Lots of pain.
>
Marc
>
>
>

Nov 3 '06 #7
Well, it depends on the intention of the class. One strategy is to have
a generic base class, but add specific functionality in a subclass.
Also, if in 2.0 I would recommend re-using the existing generic types -
and it sounds like Dictionary is the one to use here. For instance, I'm
assuming that all your "data item"s have an ID, and that product may be
subclassed - and may warrant specific (typed) collections, then
something like below. Alternatively, in *many* cases it is sufficient
to simply use a List<T>, either wrapped or unwrapped (if I was writing
a library component as a vendor, then I would wrap all the collections;
if it was just for internal use I could perhaps leave as List<Tand
just absorb the code-hack time if/when I changed the implementation to
SuperList<T>).

public abstract class DataItem {
public int Id {...}
}

public class DataItemDiction ary<T: IEnumerable<Twh ere T : DataItem
{
private readonly Dictionary<int, Titems = new Dictionary<int, T>();

public void Add(T item) {
items.Add(item. Id, item);
}
public T this[int id] {
get {return items[id];}
}
public IEnumerator<TGe tEnumerator() {
return items.Values.Ge tEnumerator();
}
// etc
}

public class Product : DataItem {
public string SkuCode {...}
}

public class ProductDictiona ry<T: DataItemDiction ary<Twhere T :
Product {
public T this[string skuCode] {
foreach(T item in this) {
if(item.SkuCode == skuCode) return item;;
}
throw new KeyNotFoundExce ption();
}
}

etc

Marc

Nov 3 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
9725
by: PK | last post by:
Hello, I am looking for help on the following. I'm trying to create a custom browser toolbar button that will do a few things. One that I'm trying to do at the moment is just simply return the URL of whatever page the user is visiting. I wanted to create a Win32 application using VB.NET. If there is a better way of doing this please let me know. I assume there needs to be some sort of client side code. I was originally leaning...
3
1881
by: Ken Varn | last post by:
I am just starting the process of creating ASP.NET server controls. I have created controls for .NET applications, but have just started with ASP.NET. I am a little confused about some areas that I am hoping someone can help clear up. 1. What is the difference between initializing a control in the constructor, vs the OnInit(), vs the CreateChildControls() methods? 2. The control that I created contains an Items collection attribute...
5
2301
by: | last post by:
Trying to learn about manipulating collections of objects, and populating these objects dynamically from datasources. Could someone post a code sample that shows the following: Instantiating a collection object -- say, a dictionary. Populating that collection object with custom objects, say, Person. What I really want to see is how to populate the properties of those Person objects from a datasource: instantiate one Person, fill...
4
2525
by: Michael K. Walter | last post by:
I'd like to create a strongly-typed collection of objects that are indexed by a string value (key is a string). I'd also like to allow users to iterate over the collection using a For-each loop where an object of the contained type is returned (instead of just the standard DictionaryEntry object). - only allow objects of type MyObj to be added to the collection - return a MyObj type in the For-each loop What's the best way to do this?
2
3316
by: Bernard Bourée | last post by:
I have a class named "Variable" with 2 properties "Name" and "Value" and the following class to handle a collection of Variable: Public Class ColVariables Inherits CollectionBase Default Public Property Item(ByVal index As Integer) As Variable Get Return CType(List(index), Variable) End Get Set(ByVal Value As Variable)
5
1894
by: aaapaul | last post by:
Hello ! I have some values stored in a xml-file. When starting my application, I read this file and store the values in a collection object. My problem is the error-handling, if the fieldname does not exist. I dont want to use try and catch. The indexof-function to check would be better, but it is not available.
18
4766
by: JohnR | last post by:
From reading the documentation, this should be a relatively easy thing. I have an arraylist of custom class instances which I want to search with an"indexof" where I'm passing an instance if the class where only the "searched" property has a value. I expected to get the index into the arraylist where I could then get the entire class instance. However, the 'indexof' is never calling my overloaded, overrides Equals method. Here is the...
0
9799
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11173
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10772
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10878
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10434
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7988
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6011
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4635
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4239
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.