Passing Functions as Parameters

Passing a Function as Parameter in C#

When I first started programming in the late 1970s, I was heavily into Pascal and the concept of passing an address as a parameter was just unheard of outside of academic circles. Procedural programming treated functions as something that were called, not passed around.

Had I known C then—which had been around since the early 1970s—I might have been more aware of function pointers. If you don’t know C that well, a pointer is a variable that holds the memory address of a variable. A function pointer is a variable that holds the address of a function. You can change the value so it points to a different function at runtime.

Click here to find C developer jobs.

First you define the function pointer. This is the hard bit with C; some function pointer definitions can be almost unreadable. In the example below a variable called fPtr is defined to hold the address of a function. The * before the fPtr indicates that it’s a pointer; that’s how pointers look in C and C++.

In C, a function pointer declaration is like a function declaration—It has a return type first and then the name of the function and any parameters that are passsed in. The only difference is instead of the function name you put the pointer variable *ftptr inside parenthesis (*fptr). So the function definition int fname(int a,int b) becomes a function pointer int (*fptr)(int a,int b).

Note I’ve set this to 0 below to initialize the variable fptr to a null pointer. That’s useful for checking that a function has been assigned to it later on before calling it.

int (*fPtr)(int,int)=0;

The variable declaration fPtr holds a pointer to a function that returns an int and takes in two ints as parameters. It might be used with a function like this one.

int add(int a,int b) {

return a + b;

}

Now we just have to assign the address of this function to fPtr using the C & operator, which returns the address of the function.

fPtr = &add;

When we want to call the function, we do the following:

int value=0;

if (fPtr != 0){

value = (*fPtr)(4,5);

}

printf(“value=%i”,value);

This outputs 9. It’s very good practice to check that a pointer is not zero before you call it. You cannot assume that the operating system will set the variable to 0. You must do this yourself, as I did above.

What Use Are Function Pointers?

To write anything non trivial in C, you have to use them. With a set of function pointers you can emulate interfaces (as used in more modern languages). To ‘implement’ an interface, you have to provide a function body for each function defined in the interface and then assign them. The problem with C and pointers is that it takes a lot of work to avoid bugs.

C++ is a superset of C, so has function pointers but also method function pointers. These let you call a method on an instance of an object.

In C#

This is where it gets more interesting. C’s main problem with pointers is type safety. C++ improves on it but there’s still a chance that you can trick the compiler and end up with nasty crashing bugs. In C#, unmanaged code pointers don’t exist and it’s very hard to trick the compiler.

C# offers delegates, anonymous methods and Lambda expressions, all of which are in a sense analagous to function pointers. What are the differences?

Upload Your ResumeEmployers want candidates like you. Upload your resume. Show them you’re awesome.

A C# delegate is like a C function pointer but a lot simpler and fully type-checked. A delegate is a type and can be used to declare a delegate variable—a variable that holds the address of a method function. C# doesn’t allow standalone functions. Instead, functions are always methods of a class.

The code below shows both an anonymous method and a delegate. Create a C# WinForms project, drop three buttons on the form and set the enabled property of buttons 2 and 3 to false. In form1.cs, inside the class declaration you’ll see just this:

public Form1()

{

InitializeComponent();

}

After that add this code:

public delegate int MyBinaryFunction(int a,int b); // delegate method signature

// delegate method

public int AddAandB(int aVar, int bVar)

{

return aVar + bVar;

}

private void button1_Click(object sender, EventArgs e)

{

button2.Enabled = true;

button2.Click += delegate // this is an anonymous methood (no name)

{

MessageBox.Show(@”Button 2 Clicked”);

button3.Enabled = true;

button3.Click += button3_Click;

};

}

private void button3_Click(object sender, EventArgs e)

{

MyBinaryFunction addfunc = AddAandB;

int total = addfunc(5, 4);

MessageBox.Show(String.Format(“Total={0}”, total));

}

This starts by declaring a delegate type MyBinaryFunction, which takes two int parameters and returns an int. The method AddAandB exactly matches this type. When we declare an instance of MyBinaryFunction called addfunc in button3_click, we can assign AddAandB to it, and then call addfunc which calls AddandB.

You might wonder why not call AddAandB directly, like this?

int total = AddAndB(5,4);

Yes, that works too, but it doesn’t have the flexibility of passing the function as a variable. It would need a code change and recompile to use another function, whereas as with a delegate it can be done just by passing in a different function.

When button 1 is clicked it adds an anonymous method to the button 2 click handler. That’s all the code following the delegate keyword inside the block. It’s code that is called when button 2 is clicked. Clicking button 1 does not run this code. This can be a bit disconcerting the first few times; clicking button 2 runs code defined inside the button 1 click handler!

Clicking button 2 adds the button 3 click handler. This hooks it to a named method button3_Click. Despite the different ways of setting up the click handler for buttons 2 and 3, the end result is the same: a block of code that is called when the button is clicked.

I’ll look at doing this with Lambda Expressions in a future article as it needs a whole article to itself.

Related Articles

Related

2 Responses to “Passing Functions as Parameters”

  1. Concerned Poster

    “Procedural programming treated functions as something that were called, not passed around.”

    I’m sorry, what? You’re saying that no one heard of functional programming in the late 1970s? Have you ever heard of a language called LISP? ML?

  2. Jim Smith

    Great article! Nice information. Functional programming may have been around for awhile, but it has really gotten a lot of attention in the past decade. Thank you! I enjoyed reading this.