If we have a ThreadLocal property (each thread has it's unique property) then which one is correct (we don't want use automatic setter/getter):
A)
private ThreadLocal<MyClass> _someProperty = new ThreadLocal<MyClass>();
public ThreadLocal<MyClass> SomeProperty
{
get
{
return _someProperty.Value;
}
set
{
_someProperty.Value = value;
}
}
B)
private ThreadLocal<MyClass> _someProperty = new ThreadLocal<MyClass>();
public MyClass SomeProperty
{
get
{
return _someProperty.Value;
}
set
{
_someProperty.Value = value;
}
}
I'm assuming you want to encapsulate the ThreadLocal<T>, so that the caller only needs to know about MyClass; in which case, you still need to access .Value explicitly, as that is where the per-thread magic happens:
private readonly ThreadLocal<MyClass> _someProperty = new ThreadLocal<MyClass>();
public MyClass SomeProperty
{
get { return _someProperty.Value; }
set { _someProperty.Value = value; }
}
You should use the second form, to ensure that you control when the value is set.
If you expose the ThreadLocal directly, your caller can write SomeProperty.Value = null, and you won't be able to prevent it.
By forcing all access to go through your class, you can add validation to the setter.
Also, the first form allows one thread to erase the property's values on other threads by replacing the entire ThreadLocal instance.
Note that your code won't compile; you need to return and set .Value.
Related
My setter code is not running here, I think by design because I am setting the same reference.
Is there syntax I can use to ensure the setter runs?
var settings = new Settings();
var a = settings.ReferenceVariable;
a.Value1++;
settings.ReferenceVariable = a; // Setter is not running here, so changes to 'a' are not persisted in database
// One workaround is to set to a different value, then set back to my value. This isn't a good solution for me
settings.ReferenceVariable = null; // Setter does run
settings.ReferenceVaraible = a; // Setter does run
public class Settings
{
public MyClass ReferenceVariable
{
get => GetSettingValueFromDatabase();
set => SetSettingValueToDatabase(value);
}
}
Edit: Thanks everyone for your help, I found the issue, I'm using Fody/PropertyChanged package, which does modify property setters, and checks for changes. Their changes aren't visible to me while debugging, so it was confusing to track down
When you say "the setter is not running" - are you saying the set => SetSettingValueToDatabase(value) line is never reached, or are you infering this only by the fact that the expected side effects from SetSettingValueToDatabase are not observed?
Because my gut feeling would be that the setter and the function SetSettingValueToDatabase itself are actually called, but MyClass has an internal optimization to skip the actual database operation if the value "hasn't changed", implemented like so:
private MyClass _cachedValue;
private bool _isLoaded = false;
private MyClass GetSettingValueFromDatabase() {
if (!_isLoaded) {
_cachedValue = DoActuallyLoadFromDatabase()
_isLoaded = true;
}
return _cachedValue;
}
private void SetSettingValueToDatabase(MyClass newValue) {
if (!_isLoaded || _cachedValue != newValue) {
DoActuallySaveToDatabase(newValue);
_cachedValue = newValue;
_isLoaded = true;
}
}
The != would then most likely fall back to object.ReferenceEquals, which would yield true since the reference of newValue and _cachedValue still match - hence no DB write or cache update, hence it looks as if the setter wasn't called, when actually just its side effect weren't triggered.
You can verify this by changing the property getter/setter to
get {
var res = GetSettingValueFromDatabase();
Debug.WriteLine($"get will return {res}");
return res;
}
set {
Debug.WriteLine($"set called with {value}");
SetSettingValueToDatabase(value);
}
My suspicion is that the debug output will be
get will return MyNamespace.MyClass
set called with MyNamespace.MyClass
set called with null
set called with MyNamespace.MyClass
rather than
get will return MyNamespace.MyClass
set called with null
set called with MyNamespace.MyClass
indicating the setter was indeed called as expected.
On a side note: a setter that triggers a database write operation is not a good design. Setters should be usually designed to be light-weight operations, not triggering a potentially locking hefty database operation. Rather use a method, that should potentially even be asynchronous.
Not clear what exactly you're doing here, but I think your comments are telling:
settings.ReferenceVariable = a; // Setter is not running here, so changes to 'a' are not persisted in database
but then you have:
settings.ReferenceVaraible = a; // Setter does run
Obviously the lines of code are exactly the same here, so my guess would be that you're expecting to link a to your Database, such that a would be a kind of a handle/portal to your database and you can modify a and get those changes telegraphed into your database.
This isn't going to work. The setter only runs when you set the value of settings, not when you set the value of a. It might be that you are updating a after the fact, but updating a doesn't force the call to SetSettingValueToDatabase.
How you handle this depends on how you want to restructure your code. I would wait to write a until you're done doing whatever operations you need to do with a, but you could also add a kind of a listener mechanic to a.
I have no idea what's in a, but you could do something like the following. This is a bit more code than I meant to write lol, but I'll put some closing comments after the code block.
public interface IChanged
{
void Subscribe(System.EventHandler subscriber);
void Unsubscribe(System.EventHandler subscriber);
}
public class MyClass : IChanged
{
private System.EventHandler subscribers;
private int myInt;
public int MyInt
{
get => myInt;
set
{
myInt = value;
subscribers?.Invoke(this, null);
}
}
private string myString;
public string MyString
{
get => myString;
set
{
myString = value;
subscribers?.Invoke(this, null);
}
}
public void Subscribe(System.EventHandler subscriber)
{
subscribers += subscriber;
}
public void Unsubscribe(System.EventHandler subscriber)
{
subscribers -= subscriber;
}
}
public class Settings
{
private MyClass myClass;
public MyClass ReferenceVariable
{
get => GetSettingValueFromDatabase();
set
{
if (myClass != null)
{
if (myClass != value)
{
myClass.Unsubscribe(OnReferenceVariableChanged);
}
}
myClass = value;
SetSettingValueToDatabase(value);
value.Subscribe(OnReferenceVariableChanged);
}
}
private void OnReferenceVariableChanged(object sender, System.EventArgs e)
{
SetSettingValueToDatabase(ReferenceVariable);
}
private MyClass GetSettingValueFromDatabase()
{
// You would get this from a Database
return new MyClass();
}
private void SetSettingValueToDatabase(MyClass myClass)
{
// do stuff
}
}
Here there's an IChanged interface that sets up a mechanism to subscribe to changes. You don't need any information here, you just need a heads up that a changed. You can slap the IChanged interface on whatever you want and use it for a variety of classes.
The trick then is to add the subscribers?.Invoke(this, null); line to each property in MyClass. If you don't use properties then you don't have a way to add this line and thus you won't get notifications if/when the fields are changed.
Then, in Settings, you keep track of a private MyClass myClass to know when you're getting a new instance of MyClass, so you can unsubscribe from the old one. Fire off your SetSettings methods, and then Settings adds itself as a subscriber to the MyClass's property changes.
Now, anytime a property changes, the MyClass class alerts all its subscribers, and the Settings subscriber in particular can use that as a trigger to re/write the settings to the database.
There's nothing special there in the Settings getter, so you might want to consider unsubscribing myClass there, setting it to whatever you pulled from the database, and hooking up the subscriber to that new instance, but I don't know anything about your code so I don't want to push that as "the" answer.
I have a property which getter should load its value only the first time. The second time it returns the loaded value without loading it again:
private Object _MemberValue;
public Object MemberValue
{
get
{
if(_MemberValue == null)
{
_MemberValue = LoadMember();
}
return _MemberValue;
}
}
In VB.NET there is the Static keyword. With it you don't have to declare a class wide member.
Public Property MemberValue as Object
Get
Static value as Object = Nothing
If (value is Nothing) Then
value = LoadMember()
End If
Return value
End Get
End Property
In C# there isn't such a keyword.
Are there better C# implementations of this problem or other patterns?
Are there better C# implementations of this problem or other patterns?
Probably not. You can use Lazy<T> as an replacement if you like, but basically it is the same as your first example. Using Static in VB.NET has some serious drawbacks, so I wouldn't use it either way.
If you prefer Lazy<T>, this is what I would use:
private Lazy<object> _MemberLazy = new Lazy<object>(LoadMember);
public object MemberValue
{
get
{
return _MemberLazy.Value;
}
}
Your initial approach seems appropriate, I have never had reason to do something different. That said if your goal here is to avoid a class level field that could potentially be written to outside the getter, perhaps something like this would work. There are a number of other ReadOnly, WriteOnce, SetOnce implementations that would also work similarly.
ReadOnlyField.cs
public class ReadOnlyField<T>
{
private bool _frozen;
private T _value;
public T Value
{
get { return _value; }
set
{
if (_frozen)
throw new InvalidOperationException();
_value = value;
}
}
public void Freeze()
{
_frozen = true;
}
}
YourObject.cs
public class YourObject
{
private readonly ReadOnlyField<object> _someMember;
public object MemberValue
{
get
{
if(_someMember.Value == null)
{
_someMember.Value = LoadMember();
_someMember.Freeze();
}
return _someMember.Value;
}
}
public YourObject()
{
_someMember = new ReadOnlyField<object>();
}
}
It's not perfect. Unlike your VB.Net example; code outside of the getter could write to the field first, but at least you're protected from it being overwritten after Freeze is called.
Do I need to declare a class-level variable to hold a property, or can I just refer to self.{propertyname} in the getter/setter?
In other words, can I do this? (where I haven't defined mongoFormId anywhere):
public string mongoFormId
{
get
{
return this.mongoFormId;
}
set
{
this.mongoFormId = value;
revalidateTransformation();
}
}
You can either use automatic accessors or implement your own. If you use automatic accessors, the C# compiler will generate a backing field for you, but if you implement your own you must manually provide a backing field (or handle the value some other way).
private string _mongoFormId;
public string mongoFormId
{
get { return this._mongoFormId; }
set
{
this._mongoFormId = value;
revalidateTransformation();
}
}
UPDATE: Since this question was asked, C# 6.0 has been released. However, even with the new syntax options, there is still no way to provide a custom setter body without the need to explicitly declare a backing field.
You need to set a field variable and store the value there, if you're going to use custom getter and setter.
With the code you have right now you will be running into a stack overflow exception. When you assign something to mongoFormId, you'll execute the line this.MongoFormId = value;. This is an assignment to mongoFormId, resulting in executing the line this.MongoFormId = value;, and so on. It won't ever stop.
The correct way is a field:
private string _mongoFormId;
public string mongoFormId {
get { return this._mongoFormId; }
set {
this._mongoFormId = value;
revalidateTransformation();
}
}
You should have a backing variable. Take a closer look:
get { return this.mongoFormId; }
Is going to call the getter on mongoFormId, which will call that code again, and again, and again! Defining a backing variable will avoid the infinite recursive call.
Check MSDN Properties Overview
While a property definition generally includes a private data member,
this is not required. The get accessor could return a value without
accessing a private data member. One example is a property whose get
method returns the system time. Properties enable data hiding, the
accessor methods hide the implementation of the property.
You can do it both the ways.
If you want to have a class level member variable then do it this way -
public class sampleClass
{
private string _mongoFormId;
public string mongoFormId {
get { return _mongoFormId; }
set {
_mongoFormId = value;
revalidateTransformation();
}
}
}
Or do this simple in class, if no need for revalidateTransformation() execution call there
public class sampleClass
{
public string mongoFormId {get; set;}
}
This won't work since you get a recursive call to the property.
If I'm not mistaken, the result will be a StackOverflowException.
You must use a variable.
private string mongoFormId;
public string MongoFormId
{
get
{
return this.mongoFormId;
}
set
{
this.mongoFormId = value;
revalidateTransformation();
}
}
If you don't have to execute revalidateTransformation, you can use the auto-property.
This will create a backingfiled for you behind the scene.
public string MongoFormId { get; set; }
With the code you wrote, you are creating a recursive endless loop on both the get and set. The this keyword refer to the current class, not the property you are in.
So yes, you need to declare a private field. And to avoid confusion, create properties following the MSDN Naming Guideline (Use Pascal case for properties, camel case for private fields). And please do the same for your methods, it should be RevalidateTransformation instead of revalidateTransformation if you follow the C# convention instead of java's.
private string mongoFormId;
public string MongoFormId
{
get
{
return mongoFormId;
}
set
{
mongoFormId = value;
RevalidateTransformation();
}
}
public string mongoFormId {
get {
return this.mongoFormId;
}
set {
this.mongoFormId = value;
revalidateTransformation();
}
}
this way you have the Function recursive on all paths
The only way i see is to use a private data member. As other boys tells.
I have created the following class based on a Singleton Pattern:
public sealed class UTrans
{
private static volatile UTrans _instance;
private static readonly object syncRoot = new Object();
private UTrans(){}
private static UTrans Instance
{
get
{
if (_instance == null)
{
lock (syncRoot)
{
if (_instance == null)
_instance = new UTrans();
}
}
return _instance;
}
}
}
Within this Class I have created an enum property and string property
private static MethodType _method; // Alphabectic 1 - 50
public static MethodType Method
{
get { return _method; }
set { _method = value; }
}
private static string _uName;
public static string UserName
{
get { return _uName; }
set { _uName = value; }
}
I also have some methods that take a number of arguments in this class. When I call the class instance in code, if the user assigns values to the properties; those values will be used. Otherwise, the values passed as arguments will be used.
This works fine in the case of the UserName property by checking for a null value on the property:
var un = UserName ?? user;
However I cannot perform the same check for the enumeration property because it seems that the property automatically assumes the 1st value of the enumeration if one is not assigned.
I tried to circumvent the issue by assigning the 1st value of the enum as "Unspecified". Then I may proceed to code as such:
var processMethod = TranslateMethodType(Method) == "Unspecified" ? method : Method;
Where TranslateMethodType is a private method that converts the selected enumeration to a equivalent string value.
I don't believe this is the most elegant approach to the issue though and would like some feedback on possible alternatives to this issue.
Is there a way to check that a value has not been set for the MethodType property by the user of the class without having to add an "Unspecified" value as the first value since this value is ONLY there as a way to indicate no value was set?
Obviously, this may not be the case if the user decides to use the value and it would yield undesirable results to construct the code this way.
Can a enumeration Method be marked as nullable???
Can a enumeration Method be marked as nullable???
Yes.
public Nullable<MyEnum> Bob(){
//stuff
}
var bob = Bob() ?? MyEnum.Default;
Yes, you can make the Method field/property nullable.
private static MethodType? _method; // Alphabectic 1 - 50
public static MethodType? Method
{
get { return _method; }
set { _method = value; }
}
Then you can do
var processMethod = Method == null ? method : Method.Value;
or
var processMethod = Method.HasValue ? Method.Value: method;
You can mark it as nullable however what you're experiencing is expected behaviour.
Value types that are members of a reference type are initialized to 0. This is why you should always provide a value of 0 for your enums. If you don't, then users of your class will never know that the class has invalid state.
I have been trying to build a user control with some custom properties set in the designer. However the control involves some interop code and settings which shouldn't be adjusted at runtime. Is there a way to stop the values being changed after they have been initially set by the designer code?
Are you able to modify the property definition? One approach is, add a sentinel to the property setter, and allow only one set operation (which would usually be done by InitializeComponent()):
private int _myProperty;
private bool _isMyPropertySet = false;
public int MyProperty
{
set
{
if (!_isMyPropertySet)
{
_isMyPropertySet = true;
_myProperty = value;
}
else
{
throw new NotSupportedException();
}
}
}
Michael provided a great answer, and it will solve your problem at runtime. However, at design time, if you need to be able to change that value more than once (it is design time, and the probability is likely high), then you will want to combine the DesignMode check with Michaels example:
private int _myProperty;
private bool _isMyPropertySet = false;
public int MyProperty
{
set
{
if (this.DesignMode || !_isMyPropertySet)
{
_isMyPropertySet = true;
_myProperty = value;
}
else
{
throw new NotSupportedException();
}
}
}
Now you will be able to edit this value to your hearts content during design, without running into that NotSupportedException() and getting a botched designer on the second set.
You could throw an exception inside the property setter?
public int SomeProperty {
set {
if(designerComplete) {
throw new IllegalOperationException();
}
}
}
Set designerComplete as a class variable - set it to true after the InitializeComponent method is called in the constructor.
The WinForms architecture provides a built-in way to test whether code is currently being executed in design mode - the Component.DesignMode property.
So you probably want an implementation something like this:
private int _foo;
public int Foo
{
get { return _foo; }
set
{
if (this.DesignMode)
throw new InvalidOperationException();
_foo = value;
}
}