I found a function in c# like this:
private Dictionary<string, Func<string>> ObtenerExtraCfgCampo(MsgDefCamp camp)
{
var extra = new Dictionary<string, Func<string>>();
extra.Add("Oddity", () => camp.Order % 2 == 0 ? "Even" : "Odd");
extra.Add("Odd", () => camp.Order % 2 == 0 ? "Odd" : string.Empty);
extra.Add("Even", () => camp.Order % 2 != 0 ? "Even" : string.Empty);
extra.Add("MsgPath", () => campo.MsgPath);
return extra;
}
Is there any utility on this? wouldn't it be better like this
private Dictionary<string, string> ObtenerExtraCfgCampo(MsgDefCamp camp)
{
var extra = new Dictionary<string, string>();
extra.Add("Oddity", camp.Order % 2 == 0 ? "Even" : "Odd");
extra.Add("Odd", camp.Order % 2 == 0 ? "Odd" : string.Empty);
extra.Add("Even", camp.Order % 2 != 0 ? "Even" : string.Empty);
extra.Add("MsgPath", campo.MsgPath);
return extra;
}
I undestand that changing camp would change the behavior of the functions. But isn't it too riski and difficult to reason about? I wonder if I'm missing the point of this
2 Answers 2
Ignoring the slight differences in type, interacting with the result of the first gives you a view onto the current state of camp
, but the second gives a view onto some previous state of camp
(I.E. when ObtenerExtraCfgCampo
was called, probably billions of nanoseconds ago).
They do different things, so are not interchangeable. It's not any more risky than any other reference to mutable state.
I've just gone through most of an app changing a bunch of Dictionary<Whatever, string>
s to Dictionary<Whatever, Func<string>>
s so that we can change language at runtime
-
the difference in type actually tells you this as welljk.– jk.2018年10月16日 09:07:42 +00:00Commented Oct 16, 2018 at 9:07
-
1@jk not strictly, but it's a strong hint. I've just gone through most of an app changing a bunch of
Dictionary<Whatever, string>
s toDictionary<Whatever, Func<string>>
s so that we can change language at runtimeCaleth– Caleth2018年10月16日 09:12:26 +00:00Commented Oct 16, 2018 at 9:12 -
@Caleth the Language example that you just said has open my eyes in the ussefullness of this :DAdrian Godoy– Adrian Godoy2018年10月16日 09:34:41 +00:00Commented Oct 16, 2018 at 9:34
To see what the point of it is, try running the two versions of the method with mutating data, eg see here for an example of what happens.
The first version, using Func
involves a closure over the MsgDefCamp
instance. In other words, when the dictionary is interrogated it gets the current value, so in my example, it reports "Even" even though the value was off when the method was called.
The second version evaluates the contents of the MsgDefCamp
instance when the method is called and stores those results in the dictionary. So even though the Order
changes, the dictionary's value doesn't change and "Odd" is reported.
It can be difficult to reason if you aren't familiar with such code. It is an incredibly useful language feature though, so it's worth becoming familiar with it.
-
On you example, seems that changing both after declaration it stills changes it's value. I would asume that changing msgDefCamp2 would not change the result.Adrian Godoy– Adrian Godoy2018年10月16日 15:01:51 +00:00Commented Oct 16, 2018 at 15:01
-
@AdrianGodoy, my apologies. That was very sloppy of me. I saw the results I was expecting so didn't proof-read the code and so posted a link to nonsense code. I've fixed it and updated the link.David Arno– David Arno2018年10月16日 15:27:30 +00:00Commented Oct 16, 2018 at 15:27
Explore related questions
See similar questions with these tags.
Func<T>
as a function that returns a T, instead mentally think of it asComputedOnDemand<T>
. A string is a string. AComputedOnDemand<string>
is a thing that can compute a string when asked. Those are different!