Any chance for "for each .NET object" in version 1

Posted by Stefan Marquardt on 06-May-2011 02:32

Hello Progress,

is there any chance to get a same easy syntax like this with 11.0:

Example from C#:

using System;
using System.IO;

DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory);
FileInfo[] fi = di.GetFiles();
foreach (FileInfo fiTemp in fi)
     Console.WriteLine(fiTemp.Name);

This is fast and easy.

Now, OOABL or ABL.NET:

define variable oDirInfo as DirectoryInfo.

define variable oFileInfo as FileInfo.

define variable oFileInfoEnum as System.Collections.IEnumerator no-undo.

define variable i as integer no-undo.

oDirInfo = new DirectoryInfo(Envirnonment.CurrentDirectory).

oFileInfoEnum = oDirInfo:GetFiles():GetEnumerator().

do i = 0 to oDirInfo:GetFiles():length - 1:

oFileInfoEnum:MoveNext().

oFileInfo = cast(oFileInfoEnum:Current, FileInfo).

lstFiles:Items:Add(oFileInfo:Name).

delete object oFileInfo.

end.

I need a variable (i) and a Enumeration Interface, perhaps there is a better way?


But the best would bei "for each" for .NET objects as possible in C#, VB.NET and possible all other .NET generating languages.

Definining and creating a new instance of an variable(object) in one line would be fine too.

Stefan

All Replies

Posted by Admin on 06-May-2011 04:20

I need a variable and a Enumeration Interface, perhaps there is a better way?

The purpose of the Enumerator is the you do NOT need the integer counter:

define variable oDirInfo as DirectoryInfo.

define variable oFileInfo as FileInfo.

define variable oFileInfoEnum as System.Collections.IEnumerator no-undo.

oDirInfo = new DirectoryInfo(Envirnonment.CurrentDirectory).

oFileInfoEnum = oDirInfo:GetFiles():GetEnumerator().

oFileInfoEnum:Reset () .

do while oFileInfoEnum:MoveNext():

oFileInfo = cast(oFileInfoEnum:Current, FileInfo).

lstFiles:Items:Add(oFileInfo:Name).

end.

A pseudo foreach could be achieved using an parameterized include file for this block

oFileInfoEnum = oDirInfo:GetFiles():GetEnumerator().

oFileInfoEnum:Reset () .

do while oFileInfoEnum:MoveNext():

oFileInfo = cast(oFileInfoEnum:Current, FileInfo).

Don't have the one I use at hand right now, but it's very simple.

delete object oFileInfo.

That's optional.

Posted by Stefan Marquardt on 06-May-2011 05:08

Mike,

perhaps you/we should tell this Progress!

I got this example of a very very new KB ;-)

ID: P185841
Title: "How to generate a list of fonts installed on a Windows system using .NET classes?"
Created: 04/13/2011Last Modified: 04/13/2011
Status: Unverified

http://progress.atgnow.com/esprogress/Group.jsp?bgroup=progress&id=p185841

One point for the improvement of the code, but i am still missing a real "for each ..."

Stefan

Posted by Admin on 06-May-2011 05:15

perhaps you/we should tell this Progress!

I got this example of a very very new KB

If I'd be you, I'd get used to MSDN for looking up documentation on using .NET objects like Enumerators, not the Progress K-Base.

There's a lot good stuff on the K-Base. But for .NET there's more good stuff on MSDN or Google.

I'm sure that most developers of "all other .NET generating languages" are using those sources as well.

Posted by Admin on 06-May-2011 05:25

I did made the suggestion once to have the 'all mighty' for-each work on something like an ICollection or whatever they like to call it in abl (.net or java flavor), it was about abl objects but if they add this new syntax option to the compiler it could be done for the .net as well (System.Collections.ICollection)... the thread (was it on peg?) ended up with a pointless discussion about whether or not they can give us only the interface and bend the language to accept the new syntax or they actually have to provide a full implementation for collections in abl, I still think it's nothing wrong if they just set the interface and let us build our own implementation even if eventually they'll come up with their own.

Posted by Admin on 06-May-2011 05:35

ended up with a pointless discussion

Were you surprised?

I still think it's nothing wrong if they just set the interface and let us build our own implementation even if eventually they'll come up with their own.

That would be the MS way where the foreach works on everything implementing System.Collections.IEnumerable, see http://msdn.microsoft.com/en-us/library/ttw7t8t6(v=vs.71).aspx

So time for a Progress.Lang.IEnumerable or Progress.Collections.IEnumeratble

Posted by Admin on 06-May-2011 06:37

Were you surprised?

not at all

That would be the MS way where the foreach works on everything implementing System.Collections.IEnumerable, see http://msdn.microsoft.com/en-us/library/ttw7t8t6(v=vs.71).aspx

So time for a Progress.Lang.IEnumerable or Progress.Collections.IEnumeratble

as I've said... iterable, enumerable or whatever they decide to call it we can live with it... just define that and let us implement on it, even if we also get the implementation we still need the interface to play with

argh, 've hit post to fast... since we are here, this could work just as well for arrays

Posted by Shelley Chase on 06-May-2011 12:27

We understand the need for an easy way to iterate through a list of OOABL objects and I appreciate that although you can implement it yourself it would be nice to have it in the language. I can't make any promises for 11.0...

-Shelley

Posted by jmls on 06-May-2011 12:40

11.0 SP1 ?

Posted by Admin on 06-May-2011 14:39

Attached is the foreach include we are using to achieve the same amount of code for iterating a collection as we'd need in C#

{foreach.i System.Windows.Forms.Control oControl in THIS-OBJECT:Controls}

    MESSAGE oControl:Text VIEW-AS ALERT-BOX.

END.

The core of the include is:

    DEFINE VARIABLE {2}           AS {1} NO-UNDO .

    DEFINE VARIABLE {2}Enumerator AS System.Collections.IEnumerator NO-UNDO .

    ASSIGN {2}Enumerator = {4}:GetEnumerator() .

    {2}Enumerator:Reset() .

    DO WHILE {2}Enumerator:MoveNext() ON ERROR UNDO, THROW:

        ASSIGN {2} = CAST({2}Enumerator:Current, {1}) . 

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/foreach.i.zip:550:0]

The only drawback is that we cannot scope the variables to the loop of the include file. So when using two or more foreach's in one method you'll need to use different variable names. Of course we could solve this with conditional compilation - but we never needed it that much.

Posted by Haikarainen on 04-Jun-2012 04:30

Maybe old thread but relevant information; We actually need more than 1 foreach in the same block, and I came up with a solution:

    DEFINE VARIABLE {2}{5}           AS {1} NO-UNDO .
    DEFINE VARIABLE {2}Enumerator{5} AS System.Collections.IEnumerator NO-UNDO .
   
    ASSIGN {2}Enumerator{5} = {4}:GetEnumerator() .
   
    {2}Enumerator{5}:Reset() .
   
    DO WHILE {2}Enumerator{5}:MoveNext() ON ERROR UNDO, THROW:
        ASSIGN {2}{5} = CAST({2}Enumerator{5}:Current, {1}) .


Pro's: Backwardscompatible: the {5} isnt needed but still separates definitions if its there, it works while still not cluttering the "virtual syntax" too much:

{foreach.i System.Object oObject in MyObjects 1}

Con's: You of course will have to replace oObject with oObject1, and it still is pretty ugly, but until this is supported natively its the best solution I can think of it so far!

Posted by Admin on 04-Jun-2012 05:16

We actually need more than 1 foreach in the same block, and I came up with a solution:

 

Interesting variation.

We actually use the optional 5th parameter with nodefine to avoid duplicate definitions. But the name suffix is also nice.

This thread is closed