I had a class similar to this, wich is basically meant to wrap a base type (int, long, bool, string, ...) and keep track of whether it has been modified or not.
public class FieldWrapper<T>
{
public bool HasBeenModified = false;
private T _value;
public T Value
{
get
{
return _value;
}
set
{
if ((_value == null && value != null) || (_value != null && !_value.Equals(value)))
{
this.HasBeenModified = true;
_value = value;
}
}
}
}
and i used it like that:
public class MyClass
{
public readonly FieldWrapper<int> a = new FieldWrapper<int>();
public readonly FieldWrapper<int> b = new FieldWrapper<int>();
public void DoThings()
{
a.Value = 2+1;
b.Value = a.Value;
}
}
but i really disliked this .value spreading everywhere, so i thought to create some implicit casts and added these lines:
public static implicit operator T(FieldWrapper<T> value)
{
return value.Value;
}
public static implicit operator FieldWrapper<T>(T value)
{
return new FieldWrapper<T>() { Value = value, HasBeenModified = true };
}
and it's almost all perfect and fine, but a thing.
public class MyClass
{
public FieldWrapper<int> a = new FieldWrapper<int>();
public FieldWrapper<int> b = new FieldWrapper<int>();
public void DoThings()
{
a = 2+1;
b = a;
}
}
Now a = 2+1 is effectively an assignment to a new object and the variable cannot be readonly anymore. b = a now works differently from the previous version: it copies a reference into b and so its HasBeenModified field.
Is this FieldWrapper pattern fixable in some way i'm missing?
Edit:
Context and what i want to achieve.
I do have a series of classes whose structure (fields) is reflected into the database. For example, if there is a
class DbClass1
{
[DbFieldAttribute]
public FieldWrapper<int> exampleField;
}
then there is also a table on the database called 'DbClass1' which has 'exampleField' as integer column.
This class is read and saved to database using auto-generated queries.
I wanted to avoid unnecessary UPDATE queries when the object did not change since the last load.
And possibly, only update the fields that really changed (i'm rethinking about this part, since for collection of items a bulk-update is probably more performing than single punctual updates, and for single updates the gain is probably not worth the effort of adding complexity to the code).
So, i basically just need a boolean for the class (not for each single field) to signal if this object/record has to be updated or it is not necessary.
my first guess would be
class DbClass1
{
private bool hasBeenModified = false;
int _exampleField;
[DbFieldAttribute]
public int exampleField
{
get
{
return exampleField;
}
set
{
if() //check if old value is different from new value
{
hasBeenModified = true;
_exampleField= value;
}
}
}
}
if there is a more compact way to do that it would be perfect
Related
I am using a get set method to loop another method. As shown below, I am trying to increase the value of Table10_3 in the ValuesForTableLooping class. In the Main method, I have called the get set property to increase the value by one.
I have 2 questions at hand,
Is there a way to call the get set method without putting it as Inc.Val = 0;?
Why does changing any value in Inc.Val = 0; not affect the outcome?
class Class2
{
public class ValuesForTableLooping
{
public static int Table10_3 = 1;
}
public static void Main()
{
Console.WriteLine(ValuesForTableLooping.Table10_3);
Increase Inc = new Increase();
Inc.Val = 0;
Console.WriteLine(ValuesForTableLooping.Table10_3);
Inc.Val = 0;
Console.WriteLine(ValuesForTableLooping.Table10_3);
Inc.Val = 0;
Console.WriteLine(ValuesForTableLooping.Table10_3);
}
public class Increase
{
private int val;
public int Val
{
get { return val; }
set { val = ValuesForTableLooping.Table10_3++; }
}
}
}
Thank you so much once again!
Your design is pretty strange and you seem to have a great misunderstanding on what properties are.
A property is nothing - as you noticed - as a get- and a set-method. So you could achieve the exact same with the following code:
public int get_Val() { return val; }
public void set_Val(int value) { val = ValuesForTableLooping.Table10_3++; }
And here is the weird thing. A setter expects a new value for your property, which is provided as value. However you don´t use that value at all in your implementation. Instead you just increase val by one, which I would call a really strange design. You either want to set the new value from the outside with this:
public void set_Val(int value) { val = value; }
or in the property-notation:
public int Val {
get { return val; }
set { val = value; }
}
which can be further simplified by using an auto-implemented property:
public int Val { get; set; }
Another - IMHO better - way is to omit the setter completely and create some IncreaseVal-method instead:
public void IncreaseVal() { ValuesForTableLooping.Table10_3++; }
Last but not least Increase is a very bad name for a class. It does not describe a thing, but something you can do with a thing.
i.e.
MyClass myClass = new MyClass() { Value = 5 };
I have a bunch of constructor calls like the one above, but now I've realized I need to add logic to the constructor, which was a massive oversight. Currently I have no constructor, so just a blank implicit default constructor.
The below code should explain my problem.
Edit: I'm not actually doing validation, that's just a simple example of constructor logic
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Test(1) + " should be true");
Console.WriteLine(new Test(0) + " should be false");
Test test = new Test(0) { Value = 1 }; // It allows this syntax, oddly, but the value that's used is the one passed as a parameter
Console.WriteLine("I wish " + test + " was true");
// This is what I have currently, but I'd like to add logic like that which exists in the parameterized constructor
//Test test = new Test() { Value = 1 } // Would ideally function just like Test(1), otherwise I have to go and change every call
// OUTPUT
// True should be true
// False should be false
// I wish False was true
Console.ReadLine();
}
}
class Test
{
public bool? IsGood { get; }
public int Value { get; set; }
// This doesn't currently exist in my class, but I'd like to add it
public Test(int value)
{
if (value == 1)
IsGood = true;
else
IsGood = false;
}
public override string ToString()
{
return IsGood.ToString();
}
}
Don't write code like this in the first place.
I'd write your code like this:
class Test
{
public static bool IsValid(int value)
{
return whatever; // test for validity here
}
public int Value { get; private set; } // Don't let anyone change it.
public Test(int value) {
if (!IsValid(value)) throw new InvalidArgumentException("value");
this.Value = value;
}
}
There, now Value is always valid; the user can know ahead of time whether it is valid or not; an attempt to set an invalid value produces an exception. This assumes that Value cannot change.
If Value can change then write it like this:
class Test
{
public static bool IsValid(int value)
{
return whatever; // test for validity here
}
private int value;
public int Value { get { return value; }
set
{
if (!IsValid(value)) throw new InvalidArgumentException("value");
this.value = value;
}
}
public Test(int value) {
this.Value = value;
}
}
Now the value is again always legal.
If it is legal for value to be invalid, then:
class Test
{
public bool IsValid
{
get
{
return whatever; // test for validity here
} // read-only property
}
public int Value { get; set; }
public Test(int value) {
this.Value = value;
}
}
Now the value can be any integer and whether it is valid or not can be tested dynamically.
Can I set members outside of a constructor while still using logic in the constructor?
Meaning, what, exactly?
Using the object initializer syntax, a constructor still runs. You may even choose which one to use, through the normal constructor overload syntax (which you seem to show, but you say it's not in your class?). The code in your constructor looks at the parameter value that is passed to it, not the property Value (which it doesn't even set). But if you meant for the two to work together, then sure…you can set the property in the constructor and set IsGood in the Value property setter.
If you're going to do it that way, then I would not bother with the logic in the constructor at all. Just set the Value property and let its setter do the rest of the work:
class Test
{
public bool? IsGood { get; private set; }
private int _value;
public int Value
{
get { return _value; }
set
{
_value = value;
IsGood = _value == 1;
}
}
public Test(int value)
{
Value = value;
}
}
I should point out that the semantics of the above is slightly different from what you seem to have started with. That is, the Value property is not read-only, and so can be set at any time. So, similarly, the IsGood property can change at any time. You previously had declared it as read-only and it was settable only in the constructor.
It's not clear from your question whether that's a problem or not. If you want IsGood to be strictly read-only (i.e. without even a private setter), then it won't be possible to do literally what you're asking for, because in the object initializer syntax, it relies on setting member properties after the constructor has already returned.
For the moment, I'll assume it's not a problem to add the private setter to the IsGood property.
Note that since IsGood apparently depends solely on the value of Value, you could even implement the above like this:
class Test
{
public bool? IsGood => _value != null ? _value == 1 : (bool?)null;
private int? _value;
public int Value
{
get { return _value ?? 0; }
set { _value = value; }
}
public Test(int value)
{
Value = value;
}
}
That is, don't even bother storing a value for IsGood. Just return the appropriate value based on the current state of the Value property (null if it's never been set, true if it's currently set to 1, and false otherwise).
I'm trying to implement a PATCH on Web API for an object that will be stored in a DB. The input object from the controller has all of the properties that can be modified but we allow the client to choose which fields to send back. We only want to update the MongoDB representation if some of the fields have changed or been set. We started using a Dirty object pattern (not sure this is a pattern) whereby when you set a property you also record that it is dirty. for instance
public class Example
{
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
TitleWasSet = true;
}
}
public bool TitleWasSet {get;set;}
}
This could work but is kind of tedious and I feel it exposes lots of logic that could be contained.
So a solution I came up with was to store the update Actions in the inbound object then reapply them to the Mongo Object in a Try Update fashion.
like this:
public class Data
{
public string Header { get; set; }
public int Rating { get; set; }
}
public class EditDataRequest
{
private readonly List<Action<Data>> _updates;
public EditDataRequest()
{
_updates = new List<Action<Data>>();
}
public string Header
{
set
{
_updates.Add(data => {data.Header = value;});
}
}
public int Rating
{
set
{
_updates.Add(data => {data.Rating = value;});
}
}
public bool TryUpdateFromMe(Data original)
{
if (_updates.Count == 0)
return false;
foreach (var update in _updates)
{
update.Invoke(original);
}
return true;
}
}
Now this would work great but it doesn't take account of the values being the same. So i then looked at changing the list of actions to a list of functions that would return a bool if there was a difference in the value.
private readonly List<Func<Data, bool>> _updates;
And then the properties would look like this:
public int Rating
{
set
{
_updates.Add(data => {
if (data.Rating != value)
{
data.Rating = value;
return true;
}
return false;
});
}
}
And the try update method...
public bool TryUpdateFromMe(Data original)
{
if (_updates.Count == 0)
return false;
bool changesRequired = false;
foreach (var update in _updates)
{
changesRequired |= update.Invoke(original);
}
return changesRequired;
}
As you can see that property set implementation is rather clunky and would make the code nasty to read.
I'd like a way of extracting the check this property value then update it to another method that I can reuse in each property - I assume this is possibly somehow but it might not be.
Of course, if you have better suggestions for how to handle the PATCH situation then I'd be happy to hear them as well.
Thanks for reading this far.
Consider this code:
public string Variable1 { get; set;}
public int Variable2 { get; set;}
public void Function()
{
// Has been Variable1 Initialized?
}
Inside the function, I want to know if a value has been sent to Variable1 & Variable2, prior to the function call,
even if the DEFAULT values have been sent, that's ok (null for string & 0 for int)
Consider using a simple wrapper like this:
public struct AssignableProperty<T>
{
private T _value;
public T Value
{
get { return _value; }
set
{
WasAssigned = true;
_value = value;
}
}
public bool WasAssigned { get; private set; }
public static implicit operator AssignableProperty<T>(T data)
{
return new AssignableProperty<T>() { Value = data };
}
public static bool operator ==(AssignableProperty<T> initial, T data)
{
return initial.Value.Equals(data);
}
public static bool operator !=(AssignableProperty<T> initial, T data)
{
return !initial.Value.Equals(data);
}
public override string ToString()
{
return Value.ToString();
}
}
Then your class'll look like this:
public class Test
{
public AssignableProperty<string> Variable1 { get; set; }
public AssignableProperty<int> Variable2 { get; set; }
public void Function()
{
if(Variable1.WasAssigned&&Variable2.WasAssigned)
//do stuff
}
}
You can go further and add throw Exception or contract to getter, so if somebody'll try to access uninitialized value it'll throw an exception or show you warning
Some basics about default value in C#:
When an instance of a class (or struct) is created, all fields are initialized to their respective default value.
For reference types, it will be null. For value types, it will be equivalent to 0. This is easily explains as the memory management ensures that new allocated memory is initialized to 0x0 bytes.
Auto-properties hide the generated field, but there is one. So the same rules apply.
Now to answer your question, the best way to make sure that values are initialized is to make a constructor with one parameter for each field/property and to hide the default constructor with no parameters:
public Yourtype(String param1, Int32 param2)
{
this.Variable1 = param1;
this.Variable2 = param2;
}
private Yourtype() { }
Other alternatives is described in #Sean and #Alex answers if only a subset of properties/fields needs to be initialized/checked. But this hides some overhead (one bool for each property/field and some indirection).
For the reference types you'll need to add a flag:
string m_Variable1;
bool m_IsVariable1Set;
public string Variable1
{
get{return m_Variable1;}
set{m_IsVariable1Set = true; m_Variable1 = value;}
}
For the value types you can use a nullable value
int? m_Variable2;
int Variable2
{
get{return m_Variable2.GetValueOrDefault();}
set{m_Variable2 = value;}
}
Which you can then check to see if it's been set by using m_Variable2.HasValue.
Well you can simply do a check on both variables to see if they have any value assigned to them in your function
public void Function()
{
if (String.IsNullOrEmpty(Variable1) && Variable2 ==0 )
{
// Variables are not assigned
}
}
I have a class with 5-6 fields that should be initialized once after the constructor runs.
public OriginalFileProcessor(IConfigManager configManager)
{
this._configManager = configManager;
this._field1 = this._configManager.GetAppSetting<int>ConfigKeys.Key1);
this._field2 = this._configManager.GetAppSetting<int>ConfigKeys.Key2);
this._field3 = this._configManager.GetAppSetting<int>ConfigKeys.Key3);
this._field4 = this._configManager.GetAppSetting<int>ConfigKeys.Key4);
this._field5 = this._configManager.GetAppSetting<int>ConfigKeys.Key5);
}
But I don't like to write logic apart from just simple assignments in the constructor.
I can't use inline initialization for field1 for example since then I can't use the _configManager instance there:
private int readonly _field1 = this._configManager.GetAppSetting<int>ConfigKeys.Key1);
If I use a readonly property then I'd have to add extra code like this:
private int? _field1;
public int Property1
{
get
{
if (!this._field1.HasValue)
{
this.__field1 = this._configManager.GetAppSetting<int>(Key1);
}
return this._field1.Value;
}
}
Is there any simpler approach for late initialization of instance fields?
Lazy<T> is a good option as suggested.
What I usually use is the following...
Providing your _field* is a nullable
In your property you can do...
return this.__field1 ?? (this.__field1 = this._configManager.GetAppSetting<int>(Key1));
EDIT:
Given comments discussion - why not just use a non static approach over Lazy<T>, e.g.
private readonly Lazy<int?> _field;
// init in ctor
_field = new Lazy<int?>(() => YourFieldInit(""));
// use in property
return _field.Value ?? 0;
EDIT 2:
And a small test to clarify the Lazy behavior:
public class DoLazy
{
Lazy<int?> _field;
public DoLazy()
{
// 'lazy' gets initialized - but `YourFieldInit` is not called yet.
_field = new Lazy<int?>(() => YourFieldInit(""));
}
int Property
{
get
{
// `YourFieldInit` is called here, first time.
return _field.Value ?? 0;
}
}
int? YourFieldInit(string test)
{ // breakpoint here
return -1;
}
public static void Test()
{
var lazy = new DoLazy();
int val1 = lazy.Property;
var val = lazy.Property;
}
}
Put a breakpoint inside the YourFieldInit - to see when it's actually called.
Call DoLazy.Test() from your e.g. Main.