anonymous blocks as delegates?

  • Thread starter Marcos Stefanakopolus
  • Start date
M

Marcos Stefanakopolus

In C# is there any way to use the concept of delegates to have multiple implementations of a particular block of code, so that you can choose between them without the overhead of possibly expensive if() or switch() logic, and without the overhead of a function call?

As an example, consider the task of resizing a bitmap from size X1,Y1 to size X2,Y2 (may be shrunk or expanded, may or may not maintain aspect ratio). Code that handles the general case looks like this:

Bitmap In = new Bitmap(...constructed from a file, let's say),
Out = new Bitmap(X2,Y2);
// BoxW and BoxH represent the size of the patch in the input image that each
// output pixel corresponds to.
int BoxW, BoxH;
BoxW = (Out.Width >= In.Width) ? 1 : (int)((double)In.Width / (double)Out.Width);
BoxH = (Out.Height >= In.Height) ? 1 : (int)((double)In.Height / (double)Out.Height);

double XFactor = (double)In.Width / (double)Out.Width,
YFactor = (double)In.Height / (double)Out.Height;
double R, G, B, // Sums for the color channels.
BoxArea; // not pre-computed because near the edges it may not == BoxW*BoxH.
Color C;
// loop over pixels in the output image,
for(int x = 0; x < Out.Width; x++)
for(int y = 0; y < Out.Height; y++)
{
R = G = B = BoxArea = 0.0;
// sum the R,G,B values of all input pixels in the box
for(int j = 0; j < BoxW; j++)
for(int k = 0; k < BoxH; k++)
if((int)((double)x*XFactor)+j < In.Width &&
(int)((double)y*YFactor)+k < In.Height)
{
C = In.GetPixel((int)((double)x*XFactor)+j,
(int)((double)y*YFactor)+k);
R += (double)(C.R);
G += (double)(C.G);
B += (double)(C.B);
BoxArea++;
}
// set output pixel to average of pixels in the box.
Out.SetPixel(x,y,Color.FromArgb((int)(R / BoxArea),(int)(G / BoxArea),(int)(B / BoxArea)));
}

This works just dandy, but if the output image is bigger than the input image, then BoxW == BoxH == 1, meaning that the above code in that case reduces to:

for(int x = 0; x < Out.Width; x++)
for(int y = 0; y < Out.Height; y++)
{
Out.SetPixel(x,y,In.GetPixel((int)((double)x*XFactor)+j,
(int)((double)y*YFactor)+k));
}

This, clearly, would be much faster. I don't want to do this...

for(int x = 0; x < Out.Width; x++)
for(int y = 0; y < Out.Height; y++)
if(BoxW == BoxH == 1) {
// fast case code
} else {
// general case code
}

....because it's silly to have to evaluate the conditional every time through the inner loop; BoxW and BoxH are loop invariants! I could use delegates to package up the fast case and the general case into separate functions, but then I'm penalized by the overhead of a function call. Is there some way to use delegates in the context of anonymous blocks of code so I could say something like:

// setup:
anonymous_block_delegate_type D;
....
if(BoxW == BoxH == 1) {
D = { Out.SetPixel(x,y,In.GetPixel((int)((double)x*XFactor)+j,
(int)((double)y*YFactor)+k)); }
} else {
D = { // general purpose code }
}
....
for(int x = 0; x < Out.Width; x++)
for(int y = 0; y < Out.Height; y++)
magic_D_invoking_syntax;

That way I could have my cake and eat it too, as it were. Any hope here?
 
G

Guest

you'd still need the same if or switch to determine which block to hook the
delegate up to. and it has to be a method. delegates are like functional
pointers, so without a method, it got nothing to point to.
 
M

Marcos Stefanakopolus

you'd still need the same if or switch to determine which block to hook
the
delegate up to. and it has to be a method. delegates are like functional
pointers, so without a method, it got nothing to point to.

Yes, I know that delegates are used to encapsulate methods, but there are
times (particularly inside deeply nested loops) where incurring method-call
overhead is a bummer. The _concept_ of delegates, as a way to abstractly
represent code that has the same pre- and post-conditions, is what I'm
trying to get at. A delegate is a type-safe pointer-to-method. I want a
generic pointer-to-code that I can use in a similar way, in order to get the
benefits of delegates without the method call overhead.

Thinking more about it from a compiler point of view, it's clear why
associating an actual delegate with an arbitrary block of code isn't going
to work: there are all sorts of issues with getting the variable bindings
inside the block to match what they would be if the block were encountered
"in situ", and of course doing so in a type-safe way would mean having some
sort of syntax for specifying the pre- and post-conditions of the block in
order to use that as the delegate's signature. Perhaps a clearer
explanation of what I'm after would be:

PointerToInstruction target; // a variable indicating which code I want to
execute
if(some_condition)
target = &label1; // pretend for a moment that we can take the address
of a label
else
target = &label2;

for(...)
for(...)
{
goto *target; // abuse C-style "dereference" syntax.
label1: {block 1}
goto label3; // let's not just fall through to block 2.
label2: {block 2}
label3: {} // compiler complains without at least an empty block
}

This way, by the time we get through the C# compiler and the .NET JIT
compiler, that "goto *target" line would get me what I want with an overhead
of one JMP instruction. I could live with that. Of course I can't get the
above structure to work because there's no actual PointerToInstruction type
to declare 'target' to be an instance of (at least, not that I've ever heard
or read about), and the above code uses gotos which are ugly. Is there some
clever way I can use reflection to implement the equivalent of the "goto
*target" line? The ironic thing, of course, is that in raw assembler code
this would be trivial to implement...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top