Seeking C# references about Ruby Code block functionality


#1

I have two rather simple class methods coded in Ruby…my own each
iterator:

Loop through each instruction in the block, yielding the result

from

the specified code block.

def each(&logic)
@instructions.each {|instr| yield instr}
end

Find the specified instruction parm (string) in the block.

Returns

nil if parm not found.

def find§
self.each {|i| return i if i.parm.index§ }
nil
end

I’m trying to recode this exact functionality in C#, and am just not
getting the Delegate stuff. Can you direct me to some online examples
or references that show how to pass a delegate into method that
implements an iterator? I’m just not getting all the new C#
terminology and syntax complexities, and I need to learn it. MSDN
isn’t helping me at all. The following is quasi psuedo mock up of
what I’m trying to accomplish.

    public void each(Delegate block)
    {
        foreach (FL_Instruction i in this.Instructions)
        {
            block;
        }
    }

    public static FL_Instruction find(string parm)
    {
        FindParm fp = delegate(FL_Instruction i) { if

(i.Parm.IndexOf(parm) > 0) { return i; } };
this.each(fp);
return null;
}

Thanks for your time and consideration,
dvn


#2

On May 17, 2007, at 08:20 , dkmd_nielsen wrote:

Find the specified instruction parm (string) in the block.

Returns

nil if parm not found.

def find§
self.each {|i| return i if i.parm.index§ }
nil
end

I know it isn’t what you’re asking but FWIW, if you code #each and
include Enumerable, you get this exact find for free.


#3

On 5/17/07, dkmd_nielsen removed_email_address@domain.invalid wrote:

        }
    }

C# gives you the yield keyword now, so I think you can code this
directly, without a delegate:

public void each()
{
foreach(FL_instruction in in this.Instructions)
yield i;
}

Haven’t used yield myself yet so YMMV. However, as you might see
below, you don’t really need this function unless you want to provide
an external iterator because it doesn’t do what you want in C#.

    public static FL_Instruction find(string parm)
    {
        FindParm fp = delegate(FL_Instruction i) { if

(i.Parm.IndexOf(parm) > 0) { return i; } };
this.each(fp);
return null;
}

In C#, delegates represent function signatures. You are wanting to
pass functions with different signatures (including return type) to
each. That works in Ruby but not C#. Instead, define a function
exists which takes a Predicate delegate (defined in the System
namespace):

// finds an individual instruction
public static FL_instruction find(string parm)
{
// “anonymous” delegate, which defines a function that takes an
FL_instruction
// and tests it against the passed in “parm” parameter.
Predicate<FL_Instruction> findParm = delegate(FL_Instruction i) {
return i.Parm.IndexOf(parm) > 0 };

FL_instruction [] found = this.findAll(findParm);
if(found.Length > 0)
return found[0];
else
return null;
}

// Function which takes a test and applies it to all the instructions
// in this class. An array of instructions which passed the test are
returned,
// or a zero-length array.
public static FL_instruction findAll(Predicate<FL_instruction> test)
{
ArrayList found = new ArrayList();
foreach(FL_instruction i in this.INstructions)
if(test(i))
found.Add(i)

return found.ToArray(); // have to convert to array of FL_instructions
}

Array.Exists (and other similar functions) will do all of this and
more, so take a look at them.

Hope that helps!

Justin


#4

Haven’t used yield myself yet so YMMV. However, as you might see
below, you don’t really need this function unless you want to provide
an external iterator because it doesn’t do what you want in C#.

Thanks for all the info, Justin. I’ll try to digest it. I want to
provide an external iterator as many classes will be using this from a
DLL. The internals of this calls are to be hidden. The purpose of
“each” is to provide the looping functionality while hiding the
details. The example I had given (in Ruby) demonstrated that I was
using the “each” internally, as well as using it externally.

I would think the delegate would work because the signature should not
change. The framework is always the same, “instruction
= ??.each(parm)”, returning the instruction that matches the parm or
nil.

Again, thanks for the info. And if others have suggestions, I would
appreciate it. Once I have that feeling of, “Ah Haa…now I got it”,
then I will be good to go in the future.

dvn