Search Unity

Action<T> possible?

Discussion in 'Scripting' started by EddieAmphlett, Mar 26, 2015.

  1. EddieAmphlett

    EddieAmphlett

    Joined:
    Jan 15, 2015
    Posts:
    3
    I'm playing around with lambdas and trying to pass arguments to them.

    This works fine:
    Action<string> logString = (strVal) => { Debug.Log(strVal); };

    However, Action<T> throws the error ' The type or namespace name `T' could not be found.'

    I've seen Action<T> used in several examples online. What is it that I'm not getting, something relating to the use of generics? The Action type? I can just carry on using the <string> type for now, but any help understanding what I'm missing would be much appreciated.
     
  2. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    I think in order for T to work you have to create a function like:

    Code (CSharp):
    1. public void Log<T>(T value)
    2. {
    3.      Action<T> log = (arg) => {Debug.Log(arg);};
    4.      log(value);
    5. }
    Correct me if I'm mistaken.

    EDIT: Fixed typo.
     
    Last edited: Mar 26, 2015
  3. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Please show us the code that gives this error.
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    The T has to come from somewhere - either from the containing method, or from the containing class. So you could use an Action<T> like this:

    Code (CSharp):
    1. void PerformActionOn<T>(T obj) {
    2.     Action<T> action = x => Debug.Log(x);
    3.     action(obj);
    4. }
    And then call it like this:

    Code (CSharp):
    1. void Example() {
    2.     int intVar = 5;
    3.     string stringVar = "five";
    4.  
    5.     PerformActionOn(intVar);
    6.     PerformActionOn(stringVar);
    7. }
    A much more usefull example is a method that takes the action, and applies it to something. Take the classic map function, which "maps" a function over a collection (ie. applies it to every element in the collection). You can implement that through using an Action, like this:

    Code (CSharp):
    1. void Map<T>(T[] array, Action<T> function) {
    2.     for (int i = 0; i < array.Length; i++) {
    3.         function(array[i]);
    4.     }
    5. }
    and you could use it like this:

    Code (CSharp):
    1. void MoveAllInArrayUp(Transform[] array) {
    2.     Action<Transform> moveAction = x => x.position = x.position + Vector3.up;
    3.     Map(moveAction, array);
    4. }
    Note that you have to type out the type of the T parameter when you declare the Action. Also note that using the letter T is completely arbitrary - it's short for "Type", but you could just as well have used "Y" or "D" or even full words like "Lollipop" or "dizIzZparta".

    You can read more about Action<T> here. I'd suggest looking into Func<TResult> here and Func<T, TResult> here. In short, where Action is a method that takes an argument of a type and returns nothing, the Func<TResult> method takes no arguments and returns and object of the type TResult, while Func<T, TResult> takes an argument of type T and returns and object of the type TResult.

    Hope that helps!
     
    Deleted User, Brominion and Fajlworks like this.
  5. EddieAmphlett

    EddieAmphlett

    Joined:
    Jan 15, 2015
    Posts:
    3
    Cheers guys, very helpful. My mistake was thinking T was more readily available than it is, and I could just throw it in like id in Objective-C or * in ActionScript. Cheers again.
     
  6. Deleted User

    Deleted User

    Guest

    T means you can put whatever you want within the < > brackets. You could write, string, int, or anything else. So if you look at the List class for example, you'll see the name of the class is List<T> which means that when you do want to use List, you have to pass in a type to it like such List<string>, List<int> but it could really be anything.