Not a full expert in C# here. Sorry in advance if this is a very common question.
consider the following property.
public bool IsOn{ get;set; }
above getter/setter property has anonymous backing field according to https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties
Is there a way for me to see what this "anonymous backing field" name is so that I can expand the setter without adding extra code. All I want to do is log the content of the values that's getting set to in a dll where this code exist. For example,
public bool IsOn
{
get;
set
{
Log(value);
"field name generated by c#" = value;
}
}
Or do I have to create a field manually every time I want to see what the value is being set to? if so it seems like a very unproductive approach to have them used when we consider about usability. Mind you this is only one of the setters I want to log out. there are many more needs logging on this specific dll
An Auto-Implemented Property is a property that has the default get- and set-accessors. If you have to add logic to them, you have to create a usual property with a backing field:
private bool _IsOn;
public bool IsOn
{
get { return _IsOn; }
set
{
Log(value);
_IsOn = value;
}
}
However, a property that is logging somewhere is not a real property anymore, that's a heavy side-effect in my opinion. I would make it a method:
private bool _isActive = false;
public void ChangeState(bool active)
{
Log(active);
_isActive = active;
}
public bool IsActivated => _isActive;
I have some doubts on the auto-implemented property. Why do we first get, and then set the value?
What you've have posted is not an auto property.
Below is an example class that contains 1 auto property and a custom property similar to what you have done.
public class MyPropertyClass
{
public MyPropertyClass(bool affectLogic)
{
_affectLogic = affectLogic;
}
private readonly bool _affectLogic;
public string MyAutoProperty { get; set; }
private string _myPropertyWithLogic;
public string MyPropertyWithLogic
{
get
{
if (_affectLogic)
_myPropertyWithLogic = "Some value";
return _myPropertyWithLogic;
}
set
{
if (_affectLogic)
{
_myPropertyWithLogic = "Some value";
}
else
{
_myPropertyWithLogic = value;
}
}
}
}
The autoproperty "MyAutoProperty" provides a mechanism for simply getting and setting property values.
What you have posted in a standard property that allows you to perhaps manipulate or return the property value based upon certain conditions. In your post you are checking to see if the value posted in is null before setting.
If you do not need to access the property outside of the class then you do not need to have the get method. If you remove the get then you are creating a "WriteOnly" property which is bad practice.
Create a public method on the class that accepts the "Alert" value. If you dont need to access the property outside of the class then dont create a property at all.
public void SetMyProperty(string value)
{
_myPropertyWithLogic = value;
}
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.
The following is a simple example of an enum which defines the state of an object and a class which shows the implementation of this enum.
public enum StatusEnum
{
Clean = 0,
Dirty = 1,
New = 2,
Deleted = 3,
Purged = 4
}
public class Example_Class
{
private StatusEnum _Status = StatusEnum.New;
private long _ID;
private string _Name;
public StatusEnum Status
{
get { return _Status; }
set { _Status = value; }
}
public long ID
{
get { return _ID; }
set { _ID = value; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
}
when populating the class object with data from the database, we set the enum value to "clean". with the goal of keeping most of the logic out of the presentation layer, how can we set the enum value to "dirty" when a property is changed.
i was thinking something along the lines of;
public string Name
{
get { return _Name; }
set
{
if (value != _Name)
{
_Name = value;
_Status = StatusEnum.Dirty;
}
}
}
in the setter of each property of the class.
does this sound like a good idea, does anyone have any better ideas on how the dirty flag can be assigned without doing so in the presentation layer.
When you really do want a dirty flag at the class level (or, for that matter, notifications) - you can use tricks like below to minimise the clutter in your properties (here showing both IsDirty and PropertyChanged, just for fun).
Obviously it is a trivial matter to use the enum approach (the only reason I didn't was to keep the example simple):
class SomeType : INotifyPropertyChanged {
private int foo;
public int Foo {
get { return foo; }
set { SetField(ref foo, value, "Foo"); }
}
private string bar;
public string Bar {
get { return bar; }
set { SetField(ref bar, value, "Bar"); }
}
public bool IsDirty { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void SetField<T>(ref T field, T value, string propertyName) {
if (!EqualityComparer<T>.Default.Equals(field, value)) {
field = value;
IsDirty = true;
OnPropertyChanged(propertyName);
}
}
protected virtual void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You might also choose to push some of that into an abstract base class, but that is a separate discussion
One option is to change it on write; another is to keep a copy of all the original values and compute the dirtiness when anyone asks for it. That has the added benefit that you can tell exactly which fields have changed (and in what way) which means you can issue minimal update statements and make merge conflict resolution slightly easier.
You also get to put all the dirtiness-checking in one place, so it doesn't pollute the rest of your code.
I'm not saying it's perfect, but it's an option worth considering.
If you want to implement it in this way, and you want to reduce the amount of code, you might consider applying Aspect Oriented Programming.
You can for instance use a compile-time weaver like PostSharp , and create an 'aspect' that can be applied to properties. This aspect then makes sure that your dirty flag is set when appropriate.
The aspect can look like this:
[Serializable]
[AttributeUsage(AttributeTargets.Property)]
public class ChangeTrackingAttribute : OnMethodInvocationAspect
{
public override void OnInvocation( MethodInvocationEventArgs e )
{
if( e.Delegate.Method.ReturnParameter.ParameterType == typeof(void) )
{
// we're in the setter
IChangeTrackable target = e.Delegate.Target as IChangeTrackable;
// Implement some logic to retrieve the current value of
// the property
if( currentValue != e.GetArgumentArray()[0] )
{
target.Status = Status.Dirty;
}
base.OnInvocation (e);
}
}
}
Offcourse, this means that the classes for which you want to implement ChangeTracking, should implement the IChangeTrackable interface (custom interface), which has at least the 'Status' property.
You can also create a custom attribute ChangeTrackingProperty, and make sure that the aspect that has been created above, is only applied to properties that are decorated with this ChangeTrackingProperty attribute.
For instance:
public class Customer : IChangeTrackable
{
public DirtyState Status
{
get; set;
}
[ChangeTrackingProperty]
public string Name
{ get; set; }
}
This is a little bit how I see it.
You can even make sure that PostSharp checks at compile-time whether classes that have properties that are decorated with the ChangeTrackingProperty attribute, implement the IChangeTrackable interface.
This method is based on a set of different concepts provided in this thread. I thought i'd put it out there for anyone that is looking for a way to do this cleanly and efficiently, as i was myself.
The key of this hybrid concept is that:
You don't want to duplicate the data to avoid bloating and resource hogging;
You want to know when the object's properties have changed from a given original/clean state;
You want to have the IsDirty flag be both accurate, and require little processing time/power to return the value; and
You want to be able to tell the object when to consider itself clean again. This is especially useful when building/working within the UI.
Given those requirements, this is what i came up with, and it seems to be working perfectly for me, and has become very useful when working against UIs and capturing user changes accurately. I have also posted an "How to use" below to show you how I use this in the UI.
The Object
public class MySmartObject
{
public string Name { get; set; }
public int Number { get; set; }
private int clean_hashcode { get; set; }
public bool IsDirty { get { return !(this.clean_hashcode == this.GetHashCode()); } }
public MySmartObject()
{
this.Name = "";
this.Number = -1;
MakeMeClean();
}
public MySmartObject(string name, int number)
{
this.Name = name;
this.Number = number;
MakeMeClean();
}
public void MakeMeClean()
{
this.clean_hashcode = this.Name.GetHashCode() ^ this.Number.GetHashCode();
}
public override int GetHashCode()
{
return this.Name.GetHashCode() ^ this.Number.GetHashCode();
}
}
It's simple enough and addresses all of our requirements:
The data is NOT duplicated for the dirty check...
This takes into account all property changes scenarios (see scenarios below)...
When you call the IsDirty property, a very simple and small Equals operation is performed and it is fully customizable via the GetHashCode override...
By calling the MakeMeClean method, you now have a clean object again!
Of course you can adapt this to encompass a bunch of different states... it's really up to you. This example only shows how to have a proper IsDirty flag operation.
Scenarios
Let's go over some scenarios for this and see what comes back:
Scenario 1
New object is created using empty constructor,
Property Name changes from "" to "James",
call to IsDirty returns True! Accurate.
Scenario 2
New object is created using paramters of "John" and 12345,
Property Name changes from "John" to "James",
Property Name changes back from "James" to "John",
Call to IsDirty returns False. Accurate, and we didn't have to duplicate the data to do it either!
How to use, a WinForms UI example
This is only an example, you can use this in many different ways from a UI.
Let's say you have a two forms ([A] and [B]).
The first([A]) is your main form, and the second([B]) is a form that allows the user to change the values within the MySmartObject.
Both the [A] and the [B] form have the following property declared:
public MySmartObject UserKey { get; set; }
When the user clicks a button on the [A] form, an instance of the [B] form is created, its property is set and it is displayed as a dialog.
After form [B] returns, the [A] form updates its property based on the [B] form's IsDirty check. Like this:
private void btn_Expand_Click(object sender, EventArgs e)
{
SmartForm form = new SmartForm();
form.UserKey = this.UserKey;
if(form.ShowDialog() == DialogResult.OK && form.UserKey.IsDirty)
{
this.UserKey = form.UserKey;
//now that we have saved the "new" version, mark it as clean!
this.UserKey.MakeMeClean();
}
}
Also, in [B], when it is closing, you can check and prompt the user if they are closing the form with unsaved changes in it, like so:
private void BForm_FormClosing(object sender, FormClosingEventArgs e)
{
//If the user is closing the form via another means than the OK button, or the Cancel button (e.g.: Top-Right-X, Alt+F4, etc).
if (this.DialogResult != DialogResult.OK && this.DialogResult != DialogResult.Ignore)
{
//check if dirty first...
if (this.UserKey.IsDirty)
{
if (MessageBox.Show("You have unsaved changes. Close and lose changes?", "Unsaved Changes", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
e.Cancel = true;
}
}
}
As you can see from the examples above, this can be a very useful thing to have since it really streamlines the UI.
Caveats
Every time you implement this, you have to customize it to the object you're using. E.g.: there's no "easy" generic way of doing this without using reflection... and if you use reflection, you lose efficiency, especially in large and complex objects.
Hopefully this helps someone.
Take a look at PostSharp (http://www.postsharp.org/).
You can easily create a Attribute which marks it as dirty you can add the attrubute to each property that needs it and it keeps all your code in one place.
Roughly speaking Create an interface which has your status in make the class implement it.
Create an attribute which can be applied on properties and cast to your interface in order to set the value when something changes one of the marked properties.
Your approach is basically how I would do it. I would just
remove the setter for the Status property:
public StatusEnum Status
{
get { return _Status; }
// set { _Status = value; }
}
and instead add a function
public SetStatusClean()
{
_Status = StatusEnum.Clean;
}
As well as SetStatusDeleted() and SetStatusPurged(), because I find it better indicates the intention.
Edit
Having read the answer by Jon Skeet, I need to reconsider my approach ;-) For simple objects I would stick with my way, but if it gets more complex, his proposal would lead to much better organised code.
If your Example_Class is lightweight, consider storing the original state and then comparing the current state to the original in order to determine the changes. If not your approach is the best because stroing the original state consumes a lot of system resources in this case.
Apart from the advice of 'consider making your type immutable', here's something I wrote up (and got Jon and Marc to teach me something along the way)
public class Example_Class
{ // snip
// all properties are public get and private set
private Dictionary<string, Delegate> m_PropertySetterMap;
public Example_Class()
{
m_PropertySetterMap = new Dictionary<string, Delegate>();
InitializeSettableProperties();
}
public Example_Class(long id, string name):this()
{ this.ID = id; this.Name = name; }
private void InitializeSettableProperties()
{
AddToPropertyMap<long>("ID", value => { this.ID = value; });
AddToPropertyMap<string>("Name", value => { this.Name = value; });
}
// jump thru a hoop because it won't let me cast an anonymous method to an Action<T>/Delegate
private void AddToPropertyMap<T>(string sPropertyName, Action<T> setterAction)
{ m_PropertySetterMap.Add(sPropertyName, setterAction); }
public void SetProperty<T>(string propertyName, T value)
{
(m_PropertySetterMap[propertyName] as Action<T>).Invoke(value);
this.Status = StatusEnum.Dirty;
}
}
You get the idea.. possible improvements: Use constants for PropertyNames & check if property has really changed.
One drawback here is that
obj.SetProperty("ID", 700); // will blow up int instead of long
obj.SetProperty<long>("ID", 700); // be explicit or use 700L
Here is how i do it.
In cases where i do not need to test for specific fields being dirty,
I have an abstract class:
public abstract class SmartWrap : ISmartWrap
{
private int orig_hashcode { get; set; }
private bool _isInterimDirty;
public bool IsDirty
{
get { return !(this.orig_hashcode == this.GetClassHashCode()); }
set
{
if (value)
this.orig_hashcode = this.orig_hashcode ^ 108.GetHashCode();
else
MakeClean();
}
}
public void MakeClean()
{
this.orig_hashcode = GetClassHashCode();
this._isInterimDirty = false;
}
// must be overridden to return combined hashcodes of fields testing for
// example Field1.GetHashCode() ^ Field2.GetHashCode()
protected abstract int GetClassHashCode();
public bool IsInterimDirty
{
get { return _isInterimDirty; }
}
public void SetIterimDirtyState()
{
_isInterimDirty = this.IsDirty;
}
public void MakeCleanIfInterimClean()
{
if (!IsInterimDirty)
MakeClean();
}
/// <summary>
/// Must be overridden with whatever valid tests are needed to make sure required field values are present.
/// </summary>
public abstract bool IsValid { get; }
}
}
As well as an interface
public interface ISmartWrap
{
bool IsDirty { get; set; }
void MakeClean();
bool IsInterimDirty { get; }
void SetIterimDirtyState();
void MakeCleanIfInterimClean();
}
This allows me to do partial saves, and preserve the IsDirty state if there is other details to save. Not perfect, but covers a lot of ground.
Example of usage with interim IsDirty State (Error wrapping and validation removed for clarity):
area.SetIterimDirtyState();
if (!UpdateClaimAndStatus(area))
return false;
area.MakeCleanIfInterimClean();
return true;
This is good for most scenarios, however for some classes i want to test for each field with a backing field of original data, and either return a list of changes or at least an enum of fields changed.
With an enum of fields changed i can then push that up through a message chain for selective update of fields in remote caches.
You could also think about boxing your variables, which comes at a performance cost, but also has its merits. It is pretty consise and you cannot accidentally change a value without setting your dirty status.
public class Variable<T>
{
private T _value;
private readonly Action<T> _onValueChangedCallback;
public Variable(Action<T> onValueChangedCallback, T value = default)
{
_value = value;
_onValueChangedCallback = onValueChangedCallback;
}
public void SetValue(T value)
{
if (!EqualityComparer<T>.Default.Equals(_value, value))
{
_value = value;
_onValueChangedCallback?.Invoke(value);
}
}
public T GetValue()
{
return _value;
}
public static implicit operator T(Variable<T> variable)
{
return variable.GetValue();
}
}
and then hook in a callback that marks your class as dirty.
public class Example_Class
{
private StatusEnum _Status = StatusEnum.New;
private Variable<long> _ID;
private Variable<string> _Name;
public StatusEnum Status
{
get { return _Status; }
set { _Status = value; }
}
public long ID => _ID;
public string Name => _Name;
public Example_Class()
{
_ID = new Variable<long>(l => Status = StatusEnum.Dirty);
_Name = new Variable<string>(s => Status = StatusEnum.Dirty);
}
}
Another method is to override the GetHashCode() method to somthing like this:
public override int GetHashCode() // or call it GetChangeHash or somthing if you dont want to override the GetHashCode function...
{
var sb = new System.Text.StringBuilder();
sb.Append(_dateOfBirth);
sb.Append(_marital);
sb.Append(_gender);
sb.Append(_notes);
sb.Append(_firstName);
sb.Append(_lastName);
return sb.ToString.GetHashCode();
}
Once loaded from the database, get the hash code of the object. Then just before you save check if the current hash code is equal to the previous hash code. if they are the same, don't save.
Edit:
As people have pointed out this causes the hash code to change - as i use Guids to identify my objects, i don't mind if the hashcode changes.
Edit2:
Since people are adverse to changing the hash code, instead of overriding the GetHashCode method, just call the method something else. The point is detecting a change not whether i use guids or hashcodes for object identification.
I often have a situation like this when creating simple data objects. I have a property called Label that should have a default based on the Name of the object. So if no label is set then the Name is used otherwise use the set Label. A simple example in C#
public class FooBat {
public string Name { get; set; }
public string Label {
get {
if (_label == null) return Name;
return _label;
}
set { _label = value; }
}
}
Now the problem is if you want to edit this object you can't just bind to the Label property or you will get the default value and it will look as if there is a value there when there really isn't. So what I end up doing is create another, read-only property that does the defaulting and I use that is all instances except for when the base object is being edited. This leads to many extra properties with weird names like LabelWithDefault. Another alternative I've tried is to make Label handle the defaulting and make a new property called RealLabel that is used for editing the base object. This is just as bad.
I've thought of moving the defaulting code somewhere else but I haven't found a good place for it in any "normal" model that does not replicate the defaulting code many times.
What I have started to do now is initialize the Label field when the Name field is set (and the Label field is not) and then treat the Label field as a normal field. This works but now the code for defaulting is tied to the wrong property. Why should the Name know that the Label field cares about it? So this is also not "right."
Does anyone have any better ways of handling this problem?
I think there is a little confusion about what I'm asking for. Basically I need two different views to the same object for two different uses. In the first is the editing of the object itself where I want unset fields to show as empty (unset). The second is for all other cases (including when the object is the value of a field of another object) where I want to show each field with its dynamically determined default. Just setting the default the first time doesn't no help because if the (in this case) Name field changes then the Label field must also change until the Label field is set.
The answers are getting closer but I still think that they are too targeted to the example I gave. I was trying to give a concrete example for expository purposes but in reality this is more of a best-practices issue. The example I gave was C# and for a string property but I have the same problem with most languages and systems that I use that have frameworks where the data access and data display are handled for you as well as for data types other than strings. Changing the object that is queried from the data source is possible but often tricky and knowing when to make the change (use a sublclass in this case but not in that one) is particularly difficult.
public class FooBat {
public string Name { get; set; }
public string Label {
get {
if (_label == null)
_label = Name;
return _label;
}
set { _label = value; }
}
}
Regarding your update:
You could subclass your object. The base-class would return null if the field has not been set and the sub-class would return your default value. Thus if you need to query if a value has been set, you would cast to the base-class.
Deleted previous answers/updates for brevity.
Update 2:
I would have to say the best way is to track whether the property has been set or not with an IsPropertySet bool. The Getter for the property would check that value to see if it should be returning its own value or the default value. And the setter for the property would set the IsPropertySet according to the set value (true if the value is not null, false if it is). The code that is using the class could then look at the IsPropertySet value to determine if it is receiving a set value or the default when it calls the Property's Getter.
public class FooBat {
public string Name { get; set; }
public bool IsLabelSet { get; set; }
public string Label {
get {
if (IsLabelSet)
return _label;
else
return Name;
}
set {
IsLabelSet = value != null;
_label = value;
}
}
}
I use a Nameable interface a lot (with getName()). Before I start, I'll suggest that you don't want to do this at all. It should be the domain of your display logic, not your domain objects. Usually it's the code consuming the FooBat that is able to make this decision in a better way than the object itself. That aside...
public interface Label{
string getLabel();
boolean isDefault(); //or isValued() or use instanceof expressions
}
public interface Nameable{
string getName();
}
public class FooBat implements Nameable {
public string Name { get; set; }
public Label Label {
get {
if (_label == null) {
_label = new DefaultLabel(this);
}
return _label;
}
set { _label = value; }
}
}
public class DefaultLabel implements Label{
public DefaultCharSequence(Nameable named){
this.named = named;
}
public string getLabel(){
return named.getName();
}
public boolean isDefault(){ return true; }
}
public class StringLabel implements Label {
...
}
It all essentially boils down to returning a better class for your label object.