I think I might have written my most generic function yet for a project I was working on yesterday. I created it with the intent of making JSON messages when I don’t know in advance the number of arguments, the order of the arguments, or even the data type of those arguments. What I ended up with was something which uses the ‘params’ keyword (which allows for a variable number of arguments) and the ‘object’ data type (the base class for all data types in C#):
public void LogEventArgs(params object args)
I only found out about this ‘object’ type when ‘var’ wasn’t sparking any joy. While var lets the compiler choose the correct variable type (‘compile-time type-inference’ as I’ve found it referred to online), object is in fact a specific data type which all other types derive from. This makes it incredibly versatile but also fairly undefined. As a handy little tidbit, you can find out whether the object’s of a particular type with logic along the lines of:
if (args[i] is [data type])
// Perform this logic
So we can use this to perform different logic if a given argument that’s been passed in is, for instance, a float, boolean, or string. You could alternatively use a switch statement if you need to do some tidier sorting, but for what I was doing yesterday I only really wanted to find out if any of the arguments were strings.
One thing I ran into, and I’d love to find out a better answer to, was how I could retrieve the original names for the variables passed in as arguments. Because as it was, I was getting the values of the variables but not their names. So I might get, for instance, ‘The Zoo’ but be unable to find out the variable name of ‘locationName’. The solution I ended up going with was just passing in the name of the variable first, then the variable itself, and sticking to this with every variable I added. Which meant this:
LogEventArgs(locationName, locationScore, locationTimeTaken);
LogEventArgs(nameof(locationName), locationName, nameof(locationScore), locationScore, nameof(locationTimeTaken), locationTimeTaken);
So a bit clunky but ultimately letting me do everything I needed to do and in as generic a way as possible (without needing lots of virtually identical methods to perform the same logic but with different arguments).
Soon as I manage to find out a refinement of this I’ll return to this topic.