1

I am working on a function of an indie game, which used to take in Action<List<Character>> as a parameter to display the Characters' info. Now I have decided that players can mod the game, so the display system can display anything else than just Characters.
I've overloaded the new display function, which now takes in Action<List<object>> as a parameter. The old function is still being used by the "Character" specific displays, and it would just pass Action<List<Character>> to the new overloaded one, but I have no idea how to cast Action<List<Character>> to Action<List<object>>.
Any help would be appreciated. I'm aware there is an alternative, which is to change all my old Action<List<Character>> to Action<List<object>>, and then cast List<object> to List<Character>.

Li-Qing
  • 11
  • 2
  • 2
    "_I have no idea how to cast `Action>` to `Action>`_" - You can't. Nothing to do with `Action` though, it's because `List` is invariant. – Johnathan Barclay May 19 '21 at 10:26
  • 4
    Does this answer your question? [C# generic inheritance and covariance part 2](https://stackoverflow.com/questions/14263964/c-sharp-generic-inheritance-and-covariance-part-2) and [C# variance problem: Assigning List as List](https://stackoverflow.com/questions/2033912/c-sharp-variance-problem-assigning-listderived-as-listbase/58783084#58783084) –  May 19 '21 at 10:27
  • You cannot cast, but you implement one based on the other, e.g. `actionOnListOfObjects = (Action>)(list => actionOnListOfCharacters(list.Cast().ToList())` – Klaus Gütter May 19 '21 at 10:27
  • 1
    The problem is that users can *modify* the list that you pass in -- they can add items. If you pass in a `List`, then can any type of object at all. If your list can actually only contain `Characters`, that's a problem. – canton7 May 19 '21 at 10:29
  • Maybe you can use [Cast](https://docs.microsoft.com/dotnet/api/system.linq.enumerable.cast) if the code lends itself to it. –  May 19 '21 at 10:30

1 Answers1

0

Unfortunately you can't cast it per se, but you can rewrite your original display function that takes an Action<List<Character>> to remap it to the "real" function that takes the Action<List<object>>:

        [Obsolete]
        internal void DisplayFunction(Action<List<Character>> charAction)
        {
            DisplayFunction((objs) =>
            {
                // I don't know if you need this type safety; 
                // depends on whether your display function 
                // might invoke the callback with anything other 
                // than Character - but I assume it could, otherwise
                // why go through this exercise?
                charAction(objs.Where(obj=>obj is Character)
                    .Select(obj=>(Character)obj)
                    .ToList()); 
            });
        }

        public void DisplayFunction (Action<List<object>> action)
        {
            // the real display function
        }
Peter Moore
  • 1,122
  • 10
  • 16