more than 1 indexer

  • Thread starter Thread starter Nikhil Patel
  • Start date Start date
N

Nikhil Patel

Hi all,
Is it possible to have more than one indexer in a class. If not, are
there any good alternative ways to achieve similar functionality.

Thanks...

-Nikhil
 
Nikhil Patel said:
Is it possible to have more than one indexer in a class.

You can as many indexers as you want as long as they each take a different
data type.
If not, are
there any good alternative ways to achieve similar functionality.

Create it as a function? :-)
 
Create it as a function? :-)

Michael,
I know I could create a function. But to make your life easier they
provide indexers in C#. So I wanted to know if there is something else that
I can use to achieve same functionality if I cannot create more than one
indexer. Because I am learning C# not an expert. Anyway, thanks for taking
your time and answering my questions.

-Nikhil
 
Hi Nikhil,
I think Michael gave you a clear answer:
Michael wrote:
"You can have as many indexers as you want as long as they each take a
different
data type."


It looks like you want to have more then one indexer, which all have the
same prototype.
Let say that you can have more then one indexer, which all have the same
prototype. How are you going to
distinguish them?

We might be able to help you more if you give us more information about your
intentions.

B\rgds
100
----- Original Message -----
From: "Nikhil Patel" <[email protected]>
Newsgroups: microsoft.public.dotnet.languages.csharp
Sent: Wednesday, July 23, 2003 2:16 PM
Subject: Re: more than 1 indexer
 
It's worth noting that in VB.NET you *can* do this, by giving the
indexers names. You can give indexers names in C#, too (with one of the
CompilerServices attributes), but you can't *use* those names.
Yes, you are right. In c# you have to chose one to be the default indexer.
C# will use this one. By default the default indexer is set to *item*.
I am not so sure how we gonna use those named indexers. I thing the idea of
the indexer is to to use it like following:

class SomeClass
{
int this[int index]
{
......
}
}

SomeClass someClass = new SomeClass();
someClass[10] =...

If we have *named* indexers we have to use them like

someClass.<indexername>[10] = ...

wich looks more like property returning an object or interface having an
indexer. It can be done with the existing c# version like:


public interface IIndexer
{
int this[int index]
{
get;
set;
}
}

class SomeClass: IIndexer
{
int IIndexer.this[int index]
{
get{....}
set{....}
}

//default indexer: obj[10] = ....
public int this[indexer]
{
get{....}
set{....}
}

//Named Indexer: obj.NamedIndexer[10] = ......
public IIndexer NamedIndexer
{
get{return this;}
}
}

I know there is more then one way to implement this and I know it could be
easier if we have named indexers.

B\rgds
100
 
If we have *named* indexers we have to use them like

someClass.<indexername>[10] = ...

wich looks more like property returning an object or interface having an
indexer.

<snip>

Yes, it does - but is that a problem? So long as it's clearly
documented, I think I'd be okay with that syntax. Perhaps you could
disallow having a straight property with that name, as otherwise you'd
have some ambiguity, but aside from that I don't see the problem with
it.
 
Hi John,
I'm not so sure of usefulness if this.
Let say I have two indexers in may class
foo.Girls = ...
foo.Boys = ...

It is more like I have two separate collections. So I want to be able to use
the class like the following:

foreach(Boy boy in foo.Boys)
{
....
}

foreach(Girl girl in foo.Girls)
{
....
}

If girls and boys are not properties returning collection objects, but named
indexers, my class has to implement IEnumerable interface twice. Which is
impossible ofcourse.

Even more
If I do it like in my previous post with interfaces

interface IGirlCollection: IEnumerable
{
......
}

interface IBoyCollection: IEnumerable
{
.......
}

class Foo: IGirlColelction, IBoyCollection
{
Girl IGirlCollection.this[int index]
{
......
}

//Impossible
IEnumerator IGirlCollection.IEnumerable.GetEnumerator()
{
}

public IGirlCollection Girls
{
get {return this;}
}

Boy IBoyCollection.this[int index]
{
......
}

//Impossible
IEnumerator IBoyCollection.IEnumerable.GetEnumerator()
{
}

public IBoyCollection Boys
{
get {return this;}
}

}

So, according me the real shame is that I cannot provide different
implementation if an intereface's method if I inherit the interface more
then once.

The same problem we are going to have if we have named indexers. Since I can
do that I don't realy miss named indexers.

B\rgds
100
 
100 said:
I'm not so sure of usefulness if this.
Let say I have two indexers in may class
foo.Girls = ...
foo.Boys = ...

It is more like I have two separate collections.


Usually - not necessarily though.
So I want to be able to use the class like the following:

foreach(Boy boy in foo.Boys)
{
....
}

foreach(Girl girl in foo.Girls)
{
....
}

If girls and boys are not properties returning collection objects, but named
indexers, my class has to implement IEnumerable interface twice. Which is
impossible ofcourse.

No, it just has to be foo.Girls which somehow implements IEnumerable or
is a collection. Perhaps you should also be able to define within a
property the way in which it's enumerated. (I'm blue-skying here, by
the way.)

The trouble with the way it is now, is that if you only want to provide
read-only access to Boys/Girls, you have to make sure that whatever the
Boys/Girls properties return are read-only - and if your underlying
data structure is an array, that's not terribly simple. (You basically
have to return a copy each time, or just tell your caller not to modify
the array.) If your underlying data structure is an ArrayList or
something similar, you may be able to return a read-only wrapper, but
then the caller has to explicitly cast (unless they *are* using
foreach), which is ugly. Either that, or you have to create a new class
just to encapsulate the collection type (as MS has done quite a lot in
the framework).

Generics will help considerably in the last point, but it's still not
entirely satisfactory.

You've certainly given me pause for thought about how to iterate over
named indexers though... there should be *some* way of doing it, I'm
sure.
 
Usually - not necessarily though. Right.

You've certainly given me pause for thought about how to iterate over
named indexers though... there should be *some* way of doing it, I'm
sure.

Indeed it is not so simple. I have been trying a lot of different design
decisions and the best so far is what the MS has done in the framework:
Internal collection classes keeping the reference to the owner of the
collection, which is instance of the outer-class. The good thing is that the
internal-class instances have access to all outer-class' stuff regardless of
the member access modifier and I don't have to make my internal logic public
to the others.

Anyway, if you come up with better ideia, I believe it will be of
everybody's help if you make a posting in the group

B\rgds
100
 
Anyway, if you come up with better ideia, I believe it will be of
everybody's help if you make a posting in the group

I'll have a think - but anything I come up with is likely to need
significant changes to C# and possibly even the CLR :)

Note that some of the iteration stuff I was talking about could
certainly be done with the future C# iterator feature, if it could be
applied to an indexer as well. eg

int[] foo; // Set this up elsewhere
public int Foo [int x]
{
get
{
return foo[value];
}

foreach
{
foreach (int i in foo)
{
yield foo;
}
}
}
 
I'll have a think - but anything I come up with is likely to need
significant changes to C# and possibly even the CLR :)
If we only could :)
Note that some of the iteration stuff I was talking about could
certainly be done with the future C# iterator feature, if it could be
applied to an indexer as well. eg

int[] foo; // Set this up elsewhere
public int Foo [int x]
{
get
{
return foo[value];
}

foreach
{
foreach (int i in foo)
{
yield foo;
}
}
}


Yes. that probably would help for indexers.
I would event be happy if I could imlement inderface's member like:
int intrfacenme1.intefacename2.interfacenameN.MemberNamae()

B\rgds
100
 
It's worth noting that in VB.NET you *can* do this, by giving the
indexers names. You can give indexers names in C#, too (with one of the
CompilerServices attributes), but you can't *use* those names. There
have been occasions where I've thought this was a shame. I can't
remember whether or not C# v2 will make this easier.


what is the difference wheather i have multiple indexers or multiple
properties which returns a collection?
i see no benefit.
 
cody said:
what is the difference wheather i have multiple indexers or multiple
properties which returns a collection?
i see no benefit.

Okay, how would you code these situations then:

1) You have an array which you wish to index in a read-only fashion. If
you have a property which returns the array, the array can be changed
by the caller. You could copy the array, of course, but that can be
expensive. An indexer makes this very easy.

2) You have a collection of references of a certain type. If you expose
IList as a property, it leaves the caller to cast, which isn't ideal.
(You also have to create the read-only wrapper for the collection if
you want it to be read-only, and if you don't make it read-only, you
don't have control over the type-safety without a bit more work.) If
you have an indexer, you can ensure type-safety for writing, and keep
the casting code local to the class to give a better interface to the
client.

Of course, by creating your own collection classes you can return an
appropriate property - but you end up with loads of such classes, as
witnessed in the framework libraries.
 
cody said:
you can use ArrayList.Readonly to return a readonly wrapper of the list but
thats is not optimal performance too.

No, note that you have an *array* you wish to index, not a list. Using
an ArrayList you end up with the type problem below. There are
definitely times when using an ArrayList instead of an array would be
horrendous for other reasons.
right, i hope generics will come soon so that won't be the problem in
future.

It will certainly help, yes.
the best way to solve the problem is imho to write a get-method which takes
the index as parameter and returns the correct value.
there is no difference to the indexer, you only have to write () instead of
[].

Indeed - but given that there *is* indexer and property support, why
not go the extra mile and have named indexers to make things more
consistent?
 
Some classes contain data-centric members, for example networks of
data that have a collection of Inbound and a collection of Outbound
nodes.

It would be nice to be able to treat those members as properties, even
though they may require further differentiation, e.g.

connectionArc = this.Inbound[connectionHost] or
connectionArc = this.Outbound[connectionHost]

Properties are nice, but it's a nuisiance to break the paradigm each
time a property maps across a set of information that is primarily
accessed via context. In the example above, no sane program would
just ask for this.Inbound, it would get a list full of many things it
didn't understand. On the other hand, having to go connectionArc =
this.Outbound(connectionHost) seems to indicating that the property
mechanism isn't rich enough.

mmm
 
Back
Top