1

It's possible to pass a reference to a variable (rather than just its value) into another function with the keyword ref. It's also possible to get a variable name with nameof(variableName). However, I'm not sure how to solve my current problem.

With Unity saving/loading, it's not uncommon to have a line like:

level = PlayerPrefs.GetInt("level", level);

I feel that rather than typing level three times in a line, I should have a short little function like:

LoadPref(ref level);

void LoadPref(ref int pref)
{
    pref = PlayerPrefs.GetInt(nameof(pref), pref);
}

Then every new pref can be added with another simple LoadPref call, writing it once and removing any potential issues with magic strings. However, the problem is that nameof(pref) returns pref, even though I really want it to return the name of the referenced variable.

Is there a way to get the name of the referenced variable as a string?

This is not a duplicate of Finding the variable name passed to a function, as for that nameof(pref) would be the solution - though I can see why their title causes confusion. The question here is if there is a way to get the name of the original reference from ref.

Thomas
  • 375
  • 2
  • 10
  • 1
    The `nameof` operator only works at _compile time_. Your method `LoadPref` will at runtime have no information about where `pref` came from and how the variable is named in your code. – René Vogt May 21 '19 at 14:06
  • That is interesting. Is there any runtime equivalent? – Thomas May 21 '19 at 14:07
  • 3
    [CallerMemberNameAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callermembernameattribute?view=netframework-4.8) – Zohar Peled May 21 '19 at 14:08
  • 3
    @ZoharPeled `CallerMemberNameAttribute` would give the the name of the method that called the `LoadPref` method. Not the variable name. Or as the docs state: 'The name of the method, property, or event from which the call originated.' – Jesse de Wit May 21 '19 at 14:12
  • How can I challenge the "duplicate" marking? `nameof(pref)` is the solution there, and this is a layer deeper - trying to get the name of a var passed with `ref`. – Thomas May 21 '19 at 14:16
  • @JessedeWit correct. My mistake. – Zohar Peled May 21 '19 at 14:19
  • @Thomas `nameof(pref)` gets you `pref`.... – Zohar Peled May 21 '19 at 14:21
  • @Thomas None of the *numerous* answers on the duplicate involve just calling `nameof` on the parameter in the method. All of the answers are addressing ways of getting what you want, namely the variable the caller provides. – Servy May 21 '19 at 14:22
  • @Thomas The question is not asking what you claim it's asking. It's asking exactly what you're asking, precisely. Have you read it? You've claimed it's answer is something radically different than it's *actual* answers, indicating you have not. – Servy May 21 '19 at 14:26
  • @Thomas you can't. Your original GetInt method is the most efficient way to do so: including the nameof the parameter in the function call. – Jesse de Wit May 21 '19 at 14:27
  • 1
    Inside the method it is not possible to get the name of the variable used outside of the method when calling the method. It's simply not possible. The best you can opt for is for the callee to pass in the name of the variable, as you have. The only thing I would change would be to use `nameof`, like this: `PlayerPrefs.GetInt(nameof(level), level)`, but there is no way to use `nameof` *inside* the method. – Lasse V. Karlsen May 21 '19 at 14:29
  • @Thomas You could probably do a variation of [this answer](https://stackoverflow.com/a/9801735/424129) where you'd say `LoadPref(() => level);`, where you could tease apart `Expression>` to get the name of `level`, compile and invoke the lambda to get `level`'s value, get the property access expression to set it, etc. We used to use this method to fake the `nameof()` operator before it was added to the language, but with this method there's a lot more information being passed. `level` might have to be a property, I don't recall. – 15ee8f99-57ff-4f92-890c-b56153 May 21 '19 at 14:29
  • Consider this, your method even allows you to pass in the result of evaluating an expression, which doesn't even *have* a variable (well, at least not one that you get to name): `PlayerPrefs.GetInt("Meaning of life", 17 + 25)` – Lasse V. Karlsen May 21 '19 at 14:30
  • @Servy I must not be explaining myself clearly. I need the string of the name (which is given well by the top few answers), and also the information contained. For example, the 52 vote answer very effectively passes the name and loses the information. Same with the 32 vote answer. – Thomas May 21 '19 at 14:31
  • Importantly, it also sets the referenced variable from within the function. It uses the full function of a referenced variable, and it would be nice to get the name simultaneously. However, I feel like @LasseVågsætherKarlsen's suggestion is as neat as I might get! – Thomas May 21 '19 at 14:34
  • @Thomas Numerous answers all still expose the value itself, including the highest scoring answer. In fact the second answer is the only one I see that *doesn't* expose the value in any way. – Servy May 21 '19 at 14:36
  • 1
    @Thomas The (now) 54 vote answer (Konrad Rudolph, `ExampleFunction(Expression> f)`) does actually provide the the method with what it needs to get and set the value -- it's just that the answer doesn't mention that, much less demonstrate how, and it's not obvious that the information is there if you don't know what `Expression` is. If the *implications* of "just use `Expression`" were clear to you, you wouldn't be asking this question. – 15ee8f99-57ff-4f92-890c-b56153 May 21 '19 at 14:51
  • Thanks @EdPlunkett. Definitely going to have to learn more on Linq to answer this satisfactorily for myself. – Thomas May 21 '19 at 14:58

0 Answers0