[Proposal] operator that means: self-initialising in setters #2299
-
See stackoverflow for sample code : How to implement a self initialising setter in C#. I want to use information hiding with a set accessor of a property. So I want to trigger the set accessor without putting any value in it. In the set acessor is the initialisation of the value, like this :
Question: Why I want to do this? Is the C# language missing something? Or am I (mis)using properties this way. The best solution I can come up with is to don't use properties for this and Use a separate GetShortRefControls() and SetShortRefControls() function. UPDATE: I (ahum...my collegue ;-) came up with this :
This private function is used as the setter value. In some way its behaving like an alias or a wrapper for the setter. Whats wrong with this? Its an extra function that would not really be needed. C# version x? Is it strange to think that UPDATE 2: Well after further thinking I came up with this :
I postfixed the methodname with List so we know a list is referenced for clarity. This is not what I really want and not efficient either because it always returns the value so I see the above code as a workaround. What I tried and did not work : ShortRefControls = SelfInitialising. This can be good solution. SelfInitialising is a variable with null value. This makes it clear what the meaning will be. Problem with this is, I have not only ShortRefControls in the tableDictionary but a lot more data with different types so that won't do the trick. What I really want is : a self initialising setter So is there a better alternative to handle this or a good advice to the Visual Studio team to extend the language? |
Beta Was this translation helpful? Give feedback.
Replies: 25 comments
-
@hhvdblom |
Beta Was this translation helpful? Give feedback.
-
This is almost certainly an abuse of the language. Your colleagues suggestion is correct. You should then make the setter private. This is a common and familiar pattern in C#. |
Beta Was this translation helpful? Give feedback.
-
Alternatively, you could use a Lazy. |
Beta Was this translation helpful? Give feedback.
-
The relevant stack overflow question is https://stackoverflow.com/questions/54801495/how-to-implement-a-self-initialising-setter-in-c-sharp I believe Bill Wagner gave you the correct answer there. |
Beta Was this translation helpful? Give feedback.
-
Lazy won't work. Lazy only gets the records the first time. If I want to reinitialize the setter with a new value with Lazy the "old" set is used and thats not what I want. |
Beta Was this translation helpful? Give feedback.
-
Well the setter isn't the right place for it then. That's not what setters do. The correct solution is a method that resets the value, as your colleague and @BillWagner suggested. |
Beta Was this translation helpful? Give feedback.
-
I know how I can code like Bill Wagner stated but I what I wanted to know if there are other ways to get this thing done. |
Beta Was this translation helpful? Give feedback.
-
Not using setters. Setters are not intended to be used for this. Methods are. |
Beta Was this translation helpful? Give feedback.
-
There is absolutely nothing wrong with Bill Wagners suggestions. |
Beta Was this translation helpful? Give feedback.
-
Why not use an event from the DataContext so that it tells your object that data has been modified and your object would then re-cache the data? |
Beta Was this translation helpful? Give feedback.
-
After data changed in the database I do a call like : ShortRefControls=null. This works, because it reloads the cache with the changed records. This can be done afer all DML-statements. What I don't like is : ShortRefControls=null. I like to write it as : ShortRefControls = SelfInitialize or something "else". Something else could be ShortRefControls=< or ShortRefControls <= or ShortRefControls=...... What it has to do is instructing the compiler that there is no value given for the setter and that the setter has the information to fill the value by itself. The only thing the compiler has to do is triggering the setter. |
Beta Was this translation helpful? Give feedback.
-
Create and call a method named ResetShortRefControls(). What is wrong with that? |
Beta Was this translation helpful? Give feedback.
-
There is nothing wrong with that, thats not the point. A guy in Holland professor Dijkstra says you have to write clean/short code for any solution. The code I wrote for the Property is clean/short. It has all the information whats needed. In this way I don't look at "pure" purpose how I should write the code, but the minimal code I need to write and keep it clean. |
Beta Was this translation helpful? Give feedback.
-
Everything should be made as simple as possible, but not simpler. Abusing properties to save a few characters is not what Dijkstra had in mind. If it was, you would see C# introduce a thousand operators for every situation under the sun, so that code is as short as possible. |
Beta Was this translation helpful? Give feedback.
-
And clear code. Hiding reinitialization behind a sentinel passed to a property is not clear. Properties are supposed to do as little "work" as possible. |
Beta Was this translation helpful? Give feedback.
-
It is, its called "Information Hiding" a concept I learned when working with the C language in 1986. I hide the dataDictionary filling in the Property. |
Beta Was this translation helpful? Give feedback.
-
It is not clean, because it does not express well what is happening. When you write
I'd say that at the same time, it has too much information (the Regarding your question in the original post:
Kind of. The case where a property can be read or written is supported well by C#. The case where a property can be read or reset is not. And a language that did support it would be better for your specific use case. But C# has to weigh the needs of many developers and their use cases and it can't possibly fully satisfy everyone. I believe your use cases is relatively rare and has a "good enough" solution (having a read-only property and a separate method that resets it), so it would not be worth it to support this directly in the language. |
Beta Was this translation helpful? Give feedback.
-
You are not "Information Hiding" by allowing a public setter to essentially do nothing but mutate the state of an object in a way that isn't intuitive nor representative of the actual operation of setting. If you wanted to follow information hiding, you would not have a public setter, instead have a private event handler that handles recaching your variable when an event is invoked that notifies you that the database has been modified. |
Beta Was this translation helpful? Give feedback.
-
@svick, I can live with the fact my use case is relatively Rare. But to be sure I wrote this Proposal so may be more use cases will popup that will justify my use case and motivate to extend Property use. I know I put my neck in a rope with this proposal because I don't walk the usual line ;-) |
Beta Was this translation helpful? Give feedback.
-
Why do you use the key public List<ShortRef_Control> ShortRefControls =>
tableDictionary.GetOrAdd<List<ShortRef_Control>>(nameof(ShortRefControls), () =>
(from src in dataContext.ShortRef_Controls select src).ToList()
);
public void ResetShortRefControls() => tableDictionary.TryRemove(nameof(ShortRefControls)); |
Beta Was this translation helpful? Give feedback.
-
The key refcontrols is only one of the keys I use. The case is that I have a Winforms application that needs to fill comboboxes. I don't want to load this data multiple times from database, so I cache all this information in a dictionary. I want to hide all those dictionary stuff behind easy Properties. The problem is when this data is changed. The dictionary must have a way to refresh its information. |
Beta Was this translation helpful? Give feedback.
-
May I suggest that you post your situation in softwareengineering.stackexchange.com or a similar page? There you can find advice on a nicer design within the bounds of the language. |
Beta Was this translation helpful? Give feedback.
-
I already did on stackoverflow??
Outlook voor Android downloaden<https://aka.ms/ghei36>
…________________________________
From: Sebastian Redl <[email protected]>
Sent: Thursday, March 7, 2019 11:45:10 AM
To: dotnet/csharplang
Cc: hhvdblom; Mention
Subject: Re: [dotnet/csharplang] [Proposal] operator that means: self-initialising in setters (#2299)
May I suggest that you post your situation in softwareengineering.stackexchange.com or a similar page? There you can find advice on a nicer design within the bounds of the language.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<https://github.com/dotnet/csharplang/issues/2299#issuecomment-470477368>, or mute the thread<https://github.com/notifications/unsubscribe-auth/Af37OMJEnA7mFfhQvqthM3kpa68-RajUks5vUO22gaJpZM4bec4r>.
|
Beta Was this translation helpful? Give feedback.
-
What I meant was (and maybe I am misunderstanding something) that it appears you are trying to hide the implementation details of the storage location being dependent on a magic string. The reason we do such things is because those strings tend to be sources of bugs when someone changes them in one location and not in another. If instead you depended on There has been some previous discussion here about having some property scoped/associated variables and constants and functions. Someday we might be able to have something that looks more like this: public List<ShortRef_Control> ShortRefControls
{
const symbol CacheKey = symbol();
void Reset() => tableDictionary.TryRemove(CacheKey);
List<ShortRef_Control> Build() => (from src in dataContext.ShortRef_Controls select src).ToList();
get => tableDictionary.GetOrAdd(CacheKey, Build);
}
// may need a method here to expose reset as public
public void ResetShortRefControls() => ShortRefControls:Reset(); (see issue #133) |
Beta Was this translation helpful? Give feedback.
-
Just use methods. If I set a value to a property, I expect that value to be set. You're abusing the language. |
Beta Was this translation helpful? Give feedback.
@hhvdblom
It is not clean, because it does not express well what is happening. When you write
ShortRefControls = null;
, then it looks like you're setting the property tonull
, but that's not what the setter does.I'd say that at the same time, it has too much information (the
null
value that is not actually relevant) and too little (it does not indicate in any way that it causes the property to be reset).Regarding your question in the original post:
Kind of. The case where a property can be read or written is supported well by C#. The case where a propert…