NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Iterating Generic .NET List

Solved!
Go to solution

Now that TestStand 4.5 supports Generic classes in .NET, how can we iterate through a simple .NET List<string>.

 

I can get the string as an object reference but I can't find any way within TS to access the values.  The only thing I can think of is a utility .NET method to convert IEnumerable<string> to an array.

 

Also, is there any support for the .NET extension methods such as .ToArray().  That would be another way at this.

 

Thanks.

 

p.s.  I did see several questions along these lines in the forum; the responses all pointed to discussion on the TestStand Beta forum which are sadly inaccessible

0 Kudos
Message 1 of 17
(7,591 Views)

HI,

 

Iterating throug generic lists is possible.

You have to use for For-StepType.

1. Getting size of list for the For-StepType

2. Inside get the indexed element

Thats all.

 

You may not use the Foreach StepType.

There is an idea for next future release of TS

just visit and rate it.

http://forums.ni.com/t5/NI-TestStand-Idea-Exchange/Foreach-StepType-that-supports-Net-System-Collect...

 

I have access to the beta-forums,

it deals with the same topic, but there was a bug in the beta which has been fixed in release version.

 

regards

 

Juergen

 

--Signature--
Sessions NI-Week 2017 2016
Feedback or kudos are welcome
0 Kudos
Message 2 of 17
(7,589 Views)

You should see that if you select your assembly in a .NET step, List<string> will be one of the options in the class dropdown (in the section at the bottom that shows the generic types used by that assembly).  In a new .NET step, you can select this as the class, choose "Use Existing Object" as your first call and pass in the object reference to your list.  You then have access to all members of List<string> including the Item property that lets you index into your list to get a string.  You should see every member including ToArray() and GetEnumerator().

 

-Jeff

Message 3 of 17
(7,581 Views)

 

Thanks for these replies.  I had missed the options to "cast" my objct to the List types.

 

This technique is not working quite as easily for iterating through a Dictionary<string, string>.

 

I would need to iterate in some way through the Keys.  TestStand sees the keys collection as an ICollection<string>.  An ICollection is not indexed, you cannot retreive items by index, nor is the collection's implementation IEnumerable<string>.GetEnumerator() exposed through TS.  Again, the extension methods for ICollection or IEnumerable are seemingly not available through TS.

 

Incidently, how would one practically iterate using GetEnumerator()?  Perhaps a While loop?

 

Thanks.

0 Kudos
Message 4 of 17
(7,570 Views)
Solution
Accepted by topic author TerrenceJ

Key collections of dictionaries are not indexable in .NET. You can call GetEnumerator() on them and store the enumerator in a TestStand Object Reference variable and then use that variable in other .NET steps to get the Current property and call MoveNext() to go to the next item. And yes, a while loop combined with MoveNext() should work.

 

Hope this helps,

-Doug

0 Kudos
Message 5 of 17
(7,568 Views)

 

I was afraid this would be the answer.

 

Fortunately I'm in control of the .NET interface; I don't think it's wise to expose these Enumerated looping constructs in TestStand to my customers.

 

Instead I think I'll shadow all Dictionaries with properties for getting just the Keys.  Something like this:

  

public ReadOnlyDictionary<string, Path> Paths { get; private set; }
public string[] PathNames { get { return Paths.Keys.ToArray(); } }

  

Thanks again.

0 Kudos
Message 6 of 17
(7,564 Views)

Hi,

 

I did it in the same way as you suggest as workaround!

I got an array of keys from the assembley,

and then "iterate" though the dictionary. (And this is working with a foreach-StepType)

 

 

Regards

Juergen

--Signature--
Sessions NI-Week 2017 2016
Feedback or kudos are welcome
0 Kudos
Message 7 of 17
(7,550 Views)

@brinko99 wrote:

 

I was afraid this would be the answer.

 

Fortunately I'm in control of the .NET interface; I don't think it's wise to expose these Enumerated looping constructs in TestStand to my customers.

 

Instead I think I'll shadow all Dictionaries with properties for getting just the Keys.  Something like this:

  

public ReadOnlyDictionary<string, Path> Paths { get; private set; }
public string[] PathNames { get { return Paths.Keys.ToArray(); } }

  

Thanks again.


In case you are curious, the reason ToArray() does not show up in TestStand is that it's an Extension Method (see the following for more details: http://msdn.microsoft.com/en-us/library/bb383977.aspx ) and TestStand does not currently support extension methods. I've submitted a request to consider adding support for such methods in the future.

 

-Doug

0 Kudos
Message 8 of 17
(7,536 Views)

 

Yes, I recognized that none of the extension methods are available through TestStand.  I second your feature request on this.  Modern .NET programming is in many ways founded on the generic IEnumerable<> interface (and associated extensions).  This makes design in .NET a breeze but suddenly I'm finding my TestStand sequences terribly complicated.

 

 

Incidentally, is it possible to iterate over only the Keys of a dictionary?  I do see how it is possible to iterate over the dictionary elements directly.

 

Using the above code example, if in TS I get just the Keys of the dictionary, TS sees this as an ICollection<string> (why not a KeyCollection?).

 

When using the Keys collection as an ICollection<string> there is no GetEnumerator() method.  Furthermore, the Root Class list does not offer an IEnumerable<string>.

 

I would be interested to know how TS determines which Type an object is when you get it and which Types populate the Root Class list.

 

Thanks.

0 Kudos
Message 9 of 17
(7,529 Views)

When I look at Dictionary<System.String, Int32>().Keys I'm seeing its return value as type: System.Collections.Generic.Dictionary<System.String, Int32>+KeyCollection

 

You are probably accessing the Keys property of an IDictionary<> rather than a Dictionary<>.

 

All public, fully-specified generic types referenced by public members should be included in the Root Class list. There is an issue in TestStand 2010 and 2010sp1 where fully specified generic types that are only referenced because another class or interface is dervived from them are not included, but this will be addressed in a future version and can be worked around by including an explicit reference to that type (e.g. make a public member use that type for one of it's parameters or return value).

 

The adapter will take whatever object reference you give it and try to cast it to the type you specify as the root class, so you can effectively cast an object to a different class or interface this way.

 

Hope this helps,

-Doug

Message 10 of 17
(7,527 Views)