473,385 Members | 2,003 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

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, ProductSearchCriteria
criteria) where ProductSearchCriteria 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 5464
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
ProductCollection.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>.FindIndex(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(Predicate<Tmatch)
{
for (int index = 0; index < collection.Count; index++)
{
if (match(collection[index])) return index;
}
return -1;
}

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

int index1 = collection.FindIndex(
delegate(YourItem item)
{
return item.Index == 5;
});

int index2 = collection.FindIndex(
delegate(YourItem item)
{
return item.ProductId == 5;
});
}

You can use the List<Tcollection 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
ProductCollection.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.Collections.Generics.IEnumerable. 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(Predicate<Tmatch)
{
for (int index = 0; index < collection.Count; index++)
{
if (match(collection[index])) return index;
}
return -1;
}

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

int index1 = collection.FindIndex(
delegate(YourItem item)
{
return item.Index == 5;
});

int index2 = collection.FindIndex(
delegate(YourItem item)
{
return item.ProductId == 5;
});
}

You can use the List<Tcollection 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
ProductCollection.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 DataItemDictionary<T: IEnumerable<Twhere 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<TGetEnumerator() {
return items.Values.GetEnumerator();
}
// etc
}

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

public class ProductDictionary<T: DataItemDictionary<Twhere T :
Product {
public T this[string skuCode] {
foreach(T item in this) {
if(item.SkuCode == skuCode) return item;;
}
throw new KeyNotFoundException();
}
}

etc

Marc

Nov 3 '06 #8

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

Similar topics

2
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...
3
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...
5
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...
4
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...
2
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...
5
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...
18
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
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...
0
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,...
0
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...

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.