Jordan Skittaraps
Jordan Skittaraps

Reputation: 41

Using a List<> to store methods in C# Unity3D?

I'm attempting to store a List of methods inside a List<dynamic>to create a part of my Quest system. I've never used Lists and I don't exactly know what the dynamickeyword does, so I'm having problems understanding.

To begin with, I've created a test function, and I'm trying to store it inside the List<dynamic>, and then output what the Test function returns through the console (Debug.Log()). Here's the code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Quests : MonoBehaviour
{
    public List<dynamic> activeQuests = new List<dynamic>();


    void Start()
    {
        activeQuests.Add(Test());
        Debug.Log(activeQuests[0]);
    }

    public bool Test()
    {
        return true;
    }
}

A red line appears under Debug.Log(activeQuests[0]); and the error message shown as below -

"One or more types required to compile a dynamic expression cannot be found. Are you missing a reference?"

How do I make this work?

Edit: I'm also looking for a way to add overload methods to each of these functions with parameters.

Upvotes: 2

Views: 2925

Answers (3)

CodeTherapist
CodeTherapist

Reputation: 2806

If the method are always parameter less I suggest to use this:

public List<System.Action> activeQuests = new List<System.Action>();

// usage
activeQuests.Add(Test)

Maybe a return value is needed. Then you should go with any Systen.Func<T ...> delegate.

    public List<System.Func<bool>> activeQuests = new List<System.Func<bool>>();

    // usage
    activeQuests.Add(Test)

Upvotes: 5

maraaaaaaaa
maraaaaaaaa

Reputation: 8193

putting () parenthesys after a method name calls the method, it does not reference the method. So with this logic: activeQuests.Add(Test()); is actually calling Test() and looking for a return value to pass into activeQuests. Instead, you want to send a reference to the Test() method into activeQuests, so you have to pass it without the parenthesys, i.e. activeQuests.Add(Test);. But activeQuests needs to be a list of methods (Action<...> or Func<...>), not a list of dynamic.

Upvotes: 0

31eee384
31eee384

Reputation: 2803

One solution is to not use dynamic. If you can make your quest methods conform to the same signature, like bool Test() as you have there, then you can store it using strong typing just fine.

Func<bool> represents a delegate that takes no parameters and returns a bool. So make a List<Func<bool>> and you'll have a list of functions that take no parameters and return a bool.

A mistake you're making is activeQuests.Add(Test());. This calls Test then adds the return value to activeQuests, but you want to add Test itself to activeQuests. Get rid of those () so you don't call the function.

Edit: If you want to pass parameters to your functions, check out the other versions of Func<>. If you add more types, you start adding parameters. For example, Func<int, bool> is a delegate that takes one int parameter and returns a bool.

If all your delegates are in a single list, it makes sense to give them all the same signature. This way you can call any of them with strong typing. For example, you could call each function in activeQuests like this:

foreach (Func<int, bool> questFunction in activeQuests)
{
    questFunction(5);
}

Similarly, check out Action and Action<...>. When you add more generic parameters, you're adding parameters the delegate takes. But Action delegates don't have return values, which might fit what you really want better. Everything else works exactly the same.

Upvotes: 1

Related Questions