Is it possible to pass an inline function as an argument?

I would like to pass an inline function as an argument. I’ll illustrate what I want using code that I want to write (but doesn’t compile).

I want to have a function called foo as follows.

void foo(List list, Function doStuff) {
  foreach(Unit u in list) {
    doStuff(u);
  }
}

and be able to call it in this manner:

foo(someList, new Function(Unit u) {
   u.Deselect();
   u.Remove();
}

which would deselect & remove all units in someList.

How can I accomplish what I want to do?

Thanks in advance.

Yes. In C#, they’re called delegates.

You can use one like this:

public class FooTest : MonoBehaviour {
	delegate void FooDelegate(int x);

	void Start() {
		CallDelegate(MyDelegate, 1);
		CallDelegate(MyDelegate, 2);
		CallDelegate(MyDelegate, 3);
	}
	
	void CallDelegate(FooDelegate del, int x) {
		del(x);
	}
	
	void MyDelegate(int x) {
		Debug.Log(x);
	}
}

Completely optional, advanced reading: C#'s generic Action and Func delegate types are very handy. So are lambda expressions.

It’s quite simple, actually.

Let’s say you have a

List<Enemy> enemyList;

You can call List.ForEach method, that accepts an Action delegate. Instead of an old C# 1.1 delegate, you can use a lambda expression for inlining it.

enemyList.ForEach( enemy =>
{
    enemy.Deselect();
    enemy.Remove();
});

If you put braces after the arrow in a lambda expression, you can have as many instructions as you want. I hope that was what you meant.

If you want something more generic so that you don’t always need to use List, but any collection really, create this class somewhere:

using System.Collections.Generic;
using System.Linq;

public static class DoForEachExtension
{
    public static void DoForEach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach(T item in collection.ToArray())
        {
            action(item);
        }
    }
}

And from now on you will be able to call the method .DoForEach(x => x.doSomething()) on arrays, lists, dictionaries, queues, … and any generic enumeration.
For example:

"This is a string".DoForEach(c => Debug.Log("This is character "+c+" in the string"));
new[]{1, 2, 3, 4}.DoForEach(n => Debug.Log("This is number "+n+" in the array"));

First you would need to declare Function as a delegate type:
delegate void Function(Unit u);

You’ll need to change List list to List< Unit> units so that the compiler actually knows what type of objects are in the list (and to use a better variable name than list).

Then to call it with an inline method:

foo(someList, delegate(Unit u)//delegate here instead of new Function
{//Bracket here because its infinitely easier to read. Personal preference I guess.
    u.Deselect();
    u.Remove();
});//Closing bracket and semicolon here to end the foo() function call.

Alternatively, you could skip declaring Function as a delegate type and instead use System.Action. So your foo method would be: void foo(List< Unit> list, System.Action< Unit> doStuff) where “System.Action< Unit>” refers to any method that takes a single Unit as a parameter.