I am not sure this is syntactically possible. If I have duplicate logic that would go in a getter/setter. Is there a way for a variable to inherit that pattern instead of re-typing the code.
private int basicVar;
public int BasicVar
{
get { return basicVar; }
set
{
if (IsServer)
{
basicVar = value;
Debug.Log("The variable name is: " + nameof(BasicVar));
//Other code
}
}
}
private int turn
public int Turn
{
//Inherits from basicVar
}
I am not sure if such a thing is possible, I was just curious.
(If it is, how could I template the private variable?)
I could do this by making it its own class, but I would prefer to keep it a primitive.
As mentioned in the comments, when needing to build reusable behavior, the preferred approach is to encapsulate the behavior in functions that can be called instead of the getter/setter of the property itself. This allows you to clearly define your expected behavior and allows you to easily compose logic by calling other methods.
public class Test
{
public bool IsServer { get; set; }
public int BasicVar { get; set }
public int Turn { get; set; }
public void UpdateBasicVar(int updatedValue)
{
if (IsServer)
{
BasicVar = updatedValue;
Debug.Log("The variable name is: " + nameof(BasicVar));
//Other code
}
}
public void UpdateTurnAndBasicVar(int updatedValue)
{
Turn = updatedValue;
Debug.Log("The variable name is: " + nameof(Turn));
UpdateBasicVar(updatedValue);
}
}
This also helps prevent side effects in your code. Typically, when using properties, C# developers expect that interacting with that property ONLY affects that property. It is not expected that updating one property would also update another.
Consider the following example:
public class SideEffects
{
private int basicVar;
public int BasicVar
{
get { return basicVar; }
set
{
if (IsServer)
{
basicVar = value;
Debug.Log("The variable name is: " + nameof(BasicVar));
//Other code
}
}
}
private int turn;
public int Turn
{
get { return turn; }
set
{
turn = value;
BasicVar = value;
}
}
}
while this is essentially functionally equivalent to the previous method-based example, it is no longer self-documenting. There is no way to determine from the public contract of the class that updating Turn will also update BasicVar, which is considered a side effect.
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.
Is there an access modifier, or combination thereof, to restrict access to an outer class only?
For the Position property of nested class PanelFragment below, I would like only the containing class ViewPagerPanels to be able to set it (via the setter, I realize this could be done through a constructor parameter also).
public class ParcelView : MXActivityView<ParcelVM>, ViewPager.IOnPageChangeListener, IFragmentToViewPagerEvent
{
private ViewPagerPanels _pagerPanels;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
_pagerPanels = new ViewPagerPanels(5); // 5: magic number, put int constant
_pagerPanels[0] = new ViewPagerPanels.PanelFragment(typeof(ViewA));
// ...
}
private class ViewPagerPanels
{
public class PanelFragment
{
public Fragment Fragment { get; set; }
// ?? - access modifer for set
public int Position { get; private set; }
}
public readonly int PANEL_COUNT;
private PanelFragment[] _panels;
public ViewPagerPanels(int count)
{
PANEL_COUNT = count;
_panels = new PanelFragment[PANEL_COUNT];
}
public PanelFragment this[int i]
{
get
{
return _panels[i];
}
set
{
_panels[i] = value;
// !! - cannot access private property
_panels[i].Position = i;
}
}
}
}
No, it's not possible to do it directly. The most restrictive access modifier, private, already allows access from within the same class. Every other modifier further expands that access.
Every class, no matter if its nested, private or public, always has access to every single of its own declared members, with no chance of applyng restrictions to itself. The closest we can get is by using a readonly field (or a getter only property) that prevents the declaring class from modifying a variable outside the constructor. But for a read-write one, we're out of options.
There is a solution for this type of protection scenarios. But you should do the following changes;
1- Replace you concrete class with an interface or abstract class and expose this to outside world
2- Implement this interface with a concrete class
3- Control the creation of this class by a factory method
4- Set the property by casting the interface (or abstract class) to your private class type
Sample code changes
public interface IPanelFragment
{
Fragment Fragment { get; set; }
// ?? - access modifer for set
int Position { get; }
}
class PanelFragment : IPanelFragment
{
public Fragment Fragment { get; set; }
// ?? - access modifer for set
public int Position { get; set; }
}
private IPanelFragment[] _panels;
public IPanelFragment CreateFragment(Fragment fragment, int pos)
{
return new PanelFragment() { Fragment= fragment, Position = pos };
}
public IPanelFragment this[int i]
{
get
{
return _panels[i];
}
set
{
_panels[i] = value;
// !! - cannot access private property
((PanelFragment)_panels[i]).Position = i;
}
}
A possible workaround
public int Position { get; private set; }
public int InitPosition { set { Position = value; } }
or, depending on your philosophical perspective concerning getter-less Properties
public void InitPosition(int value) { Position = value; }
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.
Using c# auto-implemented properties can I have a class that does the following (psuedo C# code because I get an error - which is below when trying to compile this):
public class Foo {
public String HouseName { get; private set; }
public int HouseId { get; private set; }
public int BedsTotal {
get { return (BedsTotal < 0) ? 0 : BedsTotal; }
private set;
}
}
Error 5 'House.BedsTotal.set' must declare a body because it is not marked abstract, extern, or partial c:\src\House.cs
To me it seems like I should be able to get a body for the getter and rely on the private set being auto-generated like it would be if I did a { get; private set; } but that's not working.
Do I need to go the whole way and set up member variables, take the private setter off, and use the members vars instead?
Thanks!
Yes, you'll need to set up private variables because at the moment you will end up in a loop trying to read the get {} portion because it references itself.
Set up a private backing variable like this:
private int _bedsTotal;
public int BedsTotal {
get { return (_bedsTotal < 0) ? 0 : _bedsTotal; }
private set { _bedsTotal = value; }
}
Then you can access beds through the private setter
i whould go for an even more easier approach
private int _bedsTotal;
public int BedsTotal
{
get
{
return (this._bedsTotal < 0) ? 0 : this._bedsTotal;
}
private set
{
this._bedsTotal = value;
}
}
and so you can set the value of BedsTotal like this : this.BedsTotal = [integer];, no need to used other private methods since you can make use of the set
If my understanding of the internal workings of this line is correct:
public int MyInt { get; set; }
Then it behind the scenes does this:
private int _MyInt { get; set; }
Public int MyInt {
get{return _MyInt;}
set{_MyInt = value;}
}
What I really need is:
private bool IsDirty { get; set; }
private int _MyInt { get; set; }
Public int MyInt {
get{return _MyInt;}
set{_MyInt = value; IsDirty = true;}
}
But I would like to write it something like:
private bool IsDirty { get; set; }
public int MyInt { get; set{this = value; IsDirty = true;} }
Which does not work. The thing is some of the objects I need to do the IsDirty on have dozens of properties and I'm hoping there is a way to use the auto getter/setter but still set IsDirty when the field is modified.
Is this possible or do I just have to resign myself to tripling the amount of code in my classes?
You'll need to handle this yourself:
private bool IsDirty { get; set; }
private int _myInt; // Doesn't need to be a property
Public int MyInt {
get{return _myInt;}
set{_myInt = value; IsDirty = true;}
}
There is no syntax available which adds custom logic to a setter while still using the automatic property mechanism. You'll need to write this with your own backing field.
This is a common issue - for example, when implementing INotifyPropertyChanged.
Create an IsDirty decorator (design pattern) to wrap some your properties requiring the isDirty flag functionality.
public class IsDirtyDecorator<T>
{
public bool IsDirty { get; private set; }
private T _myValue;
public T Value
{
get { return _myValue; }
set { _myValue = value; IsDirty = true; }
}
}
public class MyClass
{
private IsDirtyDecorator<int> MyInt = new IsDirtyDecorator<int>();
private IsDirtyDecorator<string> MyString = new IsDirtyDecorator<string>();
public MyClass()
{
MyInt.Value = 123;
MyString.Value = "Hello";
Console.WriteLine(MyInt.Value);
Console.WriteLine(MyInt.IsDirty);
Console.WriteLine(MyString.Value);
Console.WriteLine(MyString.IsDirty);
}
}
You can make it simple or complex. It depends on how much work you want to invest. You can use aspect oriented programming to add the aspect via an IL weaver into the IL code with e.g. PostSharp.
Or you can create a simple class that does handle the state for your property. It is so simple that the former approach only pays off if you have really many properties to handle this way.
using System;
class Dirty<T>
{
T _Value;
bool _IsDirty;
public T Value
{
get { return _Value; }
set
{
_IsDirty = true;
_Value = value;
}
}
public bool IsDirty
{
get { return _IsDirty; }
}
public Dirty(T initValue)
{
_Value = initValue;
}
}
class Program
{
static Dirty<int> _Integer;
static int Integer
{
get { return _Integer.Value; }
set { _Integer.Value = value; }
}
static void Main(string[] args)
{
_Integer = new Dirty<int>(10);
Console.WriteLine("Dirty: {0}, value: {1}", _Integer.IsDirty, Integer);
Integer = 15;
Console.WriteLine("Dirty: {0}, value: {1}", _Integer.IsDirty, Integer);
}
}
Another possibility is to use a proxy class which is generated at runtime which does add the aspect for you. With .NET 4 there is a class that does handle this aspect already for you. It is called ExpandObject which does notify you via an event when a property changes. The nice things is that ExpandoObject allows you to define at runtime any amount of properties and you get notifications about every change of a property. Databinding with WPF is very easy with this type.
dynamic _DynInteger = new ExpandoObject();
_DynInteger.Integer = 10;
((INotifyPropertyChanged)_DynInteger).PropertyChanged += (o, e) =>
{
Console.WriteLine("Property {0} changed", e.PropertyName);
};
Console.WriteLine("value: {0}", _DynInteger.Integer );
_DynInteger.Integer = 20;
Console.WriteLine("value: {0}", _DynInteger.Integer);
Yours,
Alois Kraus
I'm going to add on to Simon Hughes' answer. I propose the same thing, but add a way to allow the decorator class to update a global IsDirty flag automatically. You may find it to be less complex to do it the old-fashioned way, but it depends on how many properties you're exposing and how many classes will require the same functionality.
public class IsDirtyDecorator<T>
{
private T _myValue;
private Action<bool> _changedAction;
public IsDirtyDecorator<T>(Action<bool> changedAction = null)
{
_changedAction = changedAction;
}
public bool IsDirty { get; private set; }
public T Value
{
get { return _myValue; }
set
{
_myValue = value;
IsDirty = true;
if(_changedAction != null)
_changedAction(IsDirty);
}
}
}
Now you can have your decorator class automatically update some other IsDirty property in another class:
class MyObject
{
private IsDirtyDecorator<int> _myInt = new IsDirtyDecorator<int>(onValueChanged);
private IsDirtyDecorator<int> _myOtherInt = new IsDirtyDecorator<int>(onValueChanged);
public bool IsDirty { get; private set; }
public int MyInt
{
get { return _myInt.Value; }
set { _myInt.Value = value; }
}
public int MyOtherInt
{
get { return _myOtherInt.Value; }
set { _myOtherInt.Value = value; }
}
private void onValueChanged(bool dirty)
{
IsDirty = true;
}
}
I have created a custom Property<T> class to do common operations like that. I haven't used it thoroughly yet though, but it could be used in this scenario.
Code can be found here: http://pastebin.com/RWTWNNCU
You could use it as follows:
readonly Property<int> _myInt = new Property<int>();
public int MyInt
{
get { return _myInt.GetValue(); }
set { _myInt.SetValue( value, SetterCallbackOption.OnNewValue, SetDirty ); }
}
private void SetDirty( int oldValue, int newValue )
{
IsDirty = true;
}
The Property class handles only calling the passed delegate when a new value is passed thanks to the SetterCallbackOption parameter. This is default so it can be dropped.
UPDATE:
This won't work apparently when you need to support multiple types (besides int), because the delegate won't match then. You could ofcourse always adjust the code to suit your needs.