Dictionary, Lambda expression & Action<,>

Hey,

I am trying to pass Dictionary entries as method calls. Currently, a member on these boards suggested I used System.Action, which is great for methods that don’t take any parameters. In my case, my methods have parameters.

I am creating a Dictionary in order to check what is going to happen upon collision of two objects, instead of using an extensive switch. Thus, I have an IEnumerator which checks the distance between the two objects. Once it exits, it will invoke the appropriate method, by making a match from the string I am passing. This string is then matched with the Dictionary’s entries and invokes the corresponding method.

	private Dictionary<string, System.Action> moveUnitActions = new Dictionary <string, System.Action> ();

	public void RemoveUnit (GameObject whichUnit) {
		Destroy (whichUnit);
	}

	public IEnumerator MoveUnitTowardsUnit (GameObject whichUnit, GameObject whereTo, float speed, string collisionEvent) {
		while (Vector3.Distance (whichUnit.transform.position, whereTo.transform.position) > 15f) {
			whichUnit.transform.position = Vector3.MoveTowards (whichUnit.transform.position, whereTo.transform.position, Time.deltaTime * speed);
			yield return null;
		}
		//block that checks for the proper action
	}

	moveUnitActions ["destroy"] = () => RemoveUnit(); //PROBLEM here.

I am aware that the line indicated as “PROBLEM here.” is wrong. I tried so many different syntax combinations with lambda expressions that I no longer remember the original. In order to point the “destroy” entry to the RemoveUnit() method, I need a GameObject argument (because this is how the said method works). However, the gameobject will vary, depending on the unit I wish to destroy.

According to what I have seen, there are also Func<> and Action<>, with which I am not experienced. Is Action<> indeed the answer to my problem here and how do I modify the lambda expression? Finally, how will I invoke the method, once I find a match in the Dictionary? As simple as RemoveUnit(myUnit);?

Cheers :slight_smile:

I guess you want something like that?:

public void RemoveUnit(GameObject whichUnit)
{
    Destroy(whichUnit);
}
private Dictionary<string, System.Action<GameObject>> moveUnitActions = new Dictionary<string, System.Action<GameObject>>();
private void populate()
{
    moveUnitActions["destroy"] = RemoveUnit;
}
public void helloWorld()
{
    GameObject obja = new GameObject();
    //make sure that you have populated your dictionary before calling that:
    moveUnitActions["destroy"](obja);
}

P.S. Here is an example for your updated question:

    public void RemoveUnit(object whichUnit)
    {
        Destroy((GameObject)whichUnit);
    }
    private int someInt = 0;
    public void AddIntegerAndPostString(object pass)
    {
        Tuple<List<int>, string> iInt = (Tuple<List<int>, string>)pass;
        foreach (int o in iInt.Item1)
        {
            someInt += o;
        }
        Debug.Log(iInt.Item2);
    }
    private Dictionary<string, System.Action<object>> moveUnitActions = new Dictionary<string, System.Action<object>>();
    private void populate()
    {
        moveUnitActions["destroy"] = RemoveUnit;
        moveUnitActions["addPrint"] = AddIntegerAndPostString;
    }
    public void helloWorld()
    {
        GameObject obja = new GameObject();
        //make sure that you have populated your dictionary before calling that:
        moveUnitActions["destroy"](obja);
        List<int> ilist = new List<int>();
        ilist.Add(1);
        ilist.Add(5);
        Tuple<List<int>, string> iInt = new Tuple<List<int>, string>(ilist, "helloWorld");
        moveUnitActions["addPrint"](iInt);
    }

If you want to see a parameters as they are then you should create a custom Class/Interface (depending on the case) instead of adding functions to Dictionary.

If you need a returnable value from function then use:

 Func<object, object>

instead of:

 Action<object>

Func and Action are delegates, thus function pointers.
You can embed a function’s property into a variable.
Action returns void and Func returns the last parameter of the Func thus

    Func<int, bool>

takes an int and returns a bool.

I think you need something as simple as this

Dictionary<string, Action> moveUnitActions = new Dictionary <string, Action> ();

void RemoveUnit(GameObject whichUnit)
{
	moveUnitActions["objectName"] = () => Destroy(whichUnit);
}