Accessing List Members

  • Thread starter Thread starter AMP
  • Start date Start date
A

AMP

Hello,
I have a List that adds members in the following fashion:
for (int i = StartingPortNumber; i < (UsablePorts +
StartingPortNumber); i++)
{
string PortName = "Com" + i;
AllPorts.Add(new SerialPort(PortName));
}

At some point I want to acess a particular member by refereing to the
PortName.
Can I do that with IndexOf?
How, and if not whats the best way?
I am asking(and not trial and error) because,as of right now the I am
not connected to the ports to experiment.
Thanks
 
AMP said:
I have a List that adds members in the following fashion:
for (int i = StartingPortNumber; i < (UsablePorts +
StartingPortNumber); i++)
{
string PortName = "Com" + i;
AllPorts.Add(new SerialPort(PortName));
}

At some point I want to acess a particular member by refereing to the
PortName.
Can I do that with IndexOf?

No. That's because .IndexOf() can only look for a particular SerialPort, not
a SerialPort with a particular name. Because you don't store the reference
to the SerialPort you created anywhere other than in the list itself, you
can't look for it. If you create two SerialPort objects with the same port
names, they are still two different objects.
I am asking(and not trial and error) because,as of right now the I am
not connected to the ports to experiment.

There are three ways, one that works in this specific case and two that work
generally.

The specific solution is that there's a one-to-one correspondence between
indexes and port names in this case. So if you're looking for "Com13", all
you have to do is take .Substring(3), convert it to an integer, subtract
StartingPortNumber, and there you go. Easy as pie! But not very stable.

One non-specific solution that doesn't break when this assumption no longer
holds is to go through the list and check for each SerialPort whether it has
the name you're looking for. "AllPorts.Find(port => port.PortName ==
myPortName)" will do it. "AllPorts.Find(delegate(SerialPort port) { return
port.PortName == myPortName; })" if you're still stuck with C# 2.0.

The most general solution is to use a Dictionary (or a SortedList or
SortedDictionary), which can simply map port names to ports. This lookup
does not require searching through the entire list every time, so it scales
much better (that said, most systems have a limited number of serial ports,
so it won't matter much in this particular case). SortedList and
SortedDictionary are special Dictionaries that allow you to still access
members by index. So for example:

SortedList<string, SerialPort> AllPorts = new SortedList<string,
SerialPort>();
for (int i = StartingPortNumber; i < (UsablePorts + StartingPortNumber);
i++) {
string PortName = "Com" + i;
AllPorts.Add(PortName, new SerialPort(PortName));
}

...

SerialPort com13 = AllPorts["Com13"]; // or AllPorts.TryGetValue(...)
SerialPort com14 = AllPorts.Values[14 - StartingPortNumber];

Of course, you don't have to use names if you know they all begin with "Com"
anyway:

Dictionary<int, SerialPort> AllPorts = new Dictionary<int, SerialPort>();
for (int i = StartingPortNumber; i < (UsablePorts + StartingPortNumber);
i++) {
AllPorts.Add(i, new SerialPort(PortName));
}

...

SerialPort com13 = AllPorts[13];
 
AMP said:
I have a List that adds members in the following fashion:
for (int i = StartingPortNumber; i < (UsablePorts +
StartingPortNumber); i++)
    {
        string PortName = "Com" + i;
        AllPorts.Add(new SerialPort(PortName));
    }
At some point I want to acess a particular member by refereing to the
PortName.
Can I do that with IndexOf?

No. That's because .IndexOf() can only look for a particular SerialPort, not
a SerialPort with a particular name. Because you don't store the reference
to the SerialPort you created anywhere other than in the list itself, you
can't look for it. If you create two SerialPort objects with the same port
names, they are still two different objects.
I am asking(and not trial and error) because,as of right now the I am
not connected to the ports to experiment.

There are three ways, one that works in this specific case and two that work
generally.

The specific solution is that there's a one-to-one correspondence between
indexes and port names in this case. So if you're looking for "Com13", all
you have to do is take .Substring(3), convert it to an integer, subtract
StartingPortNumber, and there you go. Easy as pie! But not very stable.

One non-specific solution that doesn't break when this assumption no longer
holds is to go through the list and check for each SerialPort whether it has
the name you're looking for. "AllPorts.Find(port => port.PortName ==
myPortName)" will do it. "AllPorts.Find(delegate(SerialPort port) { return
port.PortName == myPortName; })" if you're still stuck with C# 2.0.

The most general solution is to use a Dictionary (or a SortedList or
SortedDictionary), which can simply map port names to ports. This lookup
does not require searching through the entire list every time, so it scales
much better (that said, most systems have a limited number of serial ports,
so it won't matter much in this particular case). SortedList and
SortedDictionary are special Dictionaries that allow you to still access
members by index. So for example:

   SortedList<string, SerialPort> AllPorts = new SortedList<string,
SerialPort>();
   for (int i = StartingPortNumber; i < (UsablePorts + StartingPortNumber);
i++) {
     string PortName = "Com" + i;
     AllPorts.Add(PortName, new SerialPort(PortName));
   }

   ...

   SerialPort com13 = AllPorts["Com13"]; // or AllPorts.TryGetValue(...)
   SerialPort com14 = AllPorts.Values[14 - StartingPortNumber];

Of course, you don't have to use names if you know they all begin with "Com"
anyway:

   Dictionary<int, SerialPort> AllPorts = new Dictionary<int, SerialPort>();
   for (int i = StartingPortNumber; i < (UsablePorts + StartingPortNumber);
i++) {
     AllPorts.Add(i, new SerialPort(PortName));
   }

   ...

   SerialPort com13 = AllPorts[13];

J.,
Thanks for the detailed explanation!!
Mike
 
Back
Top