force get/set access of private variables for private properties - c#

If I have a private variable that I want to have some internal validation on, and I want to keep that validation in one place, I put it behind a getter/setter and only access it thorugh that getter/setter. That's useful when dealing with public properties, because the other code cannot access the private variable, but when I'm dealing with object inside the class itself, is there any way to enforce the getter/setter?
private int _eyeOrientation;
private int eyeOrientation
{
get
{
return _eyeOrientation;
}
set
{
if (value < 0)
{
_eyeOrientation = 0;
}
else
{
_eyeOrientation = value % 360;
}
}
}
The issue here being that the other functions in the class may accidentally modify
_eyeOrientation = -1;
which would throw the program into a tizzy. Is there any way to get that to throw a compiler error?

Sounds like you need a angle type.
// Non mutable Angle class with a normalized, integer angle-value
public struct Angle
{
public Angle(int value)
{
Value = value;
}
private angle;
public Value
{
get { return angle; }
private set { angle = Normalize(value); }
}
public static int Normalize(int value)
{
if (value < 0) return 360 - (value % 360);
return value % 360;
}
}
public class SomeClass
{
public Angle EyeOrientation { get; set; }
}
If you have a certain kind of value, like angles, money, weight or whatever, it is always a good praxis to make it a own type, even if the value itself is stored in a int, decimal etc. This type makes your interfaces clearer and typesafe. It is not the same if you expect an Angle or a integer value as argument of some method.

In general, you shouldn't worry about this. Class members can still use the properties, if you don't want to put the checking in the class itself.
If your class is getting so large that you no longer trust methods inside the class, I'd think that it's time to start refactoring and breaking this into smaller classes that are more easily managable.

You could possibly define it in a nested class.
public class NeedsEye
{
Eye _eye = new Eye();
public NeedsEye()
{
// now, here, any access to the property must be made through the
// _eye variable. The Eye class has access to any of the properties
// and members of the NeedsEye class, but the NeedsEye class has not
// any access to members of the Eye class.
}
private class Eye
{
private int _orientation;
public int Orientation
{
get { return _orientation; }
if (value < 0)
{
_eyeOrientation = 0;
}
else
{
_eyeOrientation = value % 360;
}
}
}
}

You can mark the field as obsolete so that the compiler will generate a warning if you try to access it, and then suppress that warning for the property getter/setter.
The warning codes that you'd need to suppress are CS0612 for the plain Obsolete attribute and CS0618 if the attribute has a custom message.
In general I'd consider this a bit of a hack and try to avoid it if possible. A better solution would be to comment the code appropriately and train your fellow developers so that they'll do the right thing.
[Obsolete("Please use the EyeOrientation property instead.")]
private int _eyeOrientation;
public int EyeOrientation
{
#pragma warning disable 612, 618
get
{
return _eyeOrientation;
}
set
{
_eyeOrientation = (value > 0) ? value % 360 : 0;
}
#pragma warning restore 612, 618
}

Just put your private attribute and public getters/setters into a private class.
Then only the getter and setter can access the private attribute.
It is overkill but would work. :)

Depending on your tools you could look into enforcing a coding convention not allowing direct access to a private member outside a get/set
Might be some more work but you won't have to create a series of wrapper classes.

Related

How to avoid elegantly primitive obsession in C#

For a class Foo I need an int-like property SanityCheckPeriod that allows only values between two limits (say 1 till 7).
What is an elegant way to implement this requirement - maybe with attributes in a declarative manner?
(because I need that pattern multiple times and for expressiveness it would be great to see the limits directly attached to the property.
The idea would be something like this:
public class Foo
{
[RangeAttribute(min: 1, max: 7)]
public Period SanityCheckPeriod { get; }
...
}
public class Period
{
private int _days;
private int _max;
private int _min;
public int Days
{
get => _days;
private set
{
if (_min <= value)
throw new ArgumentExcpetion($"Period must be equal or larger than {_min} day(s).");
if (value <= _max)
throw new ArgumentExcpetion($"Period must be equal or smaller than {_max} days.");
_days = value;
}
}
public Period(int days)
{
// access the RangeAttribute here
// how to do?
// and set _min and _max
}
}
[AttributeUsage(AttributeTargets.Property)]
public class RangeAttribute : Attribute
{
public int Min { get; }
public int Max { get; }
public RangeAttribute(int min, int max)
{
Min = min;
Max = max;
}
}
If you ONLY need exact and wellknown sanity checks, then you could opt for extension methods:
public static void SanityCheckPeriod(this int value, int min, int max)
{
//check sanity
}
An elegant way to achieve this in general is with Aspect Oriented Programming which C# doesn't support OOTB. PostSharp is well documented (I'm not affiliated with them) but I don't know if any of their licenses satisfies your needs.
If bringing your own aspect is what you prefer, then you will have to accept that you need to access your object via an "interpreter".
I've seen an example where all objects are accessed via a factory where all objects returned are wrappers which scans the object for custom attributes. So that's a way where BYO aspect oriented code is preferred and where the gritty code is hidden in a single place leaving the rest of the code elegant, then that's a solution as well.
I'm assuming you're not working in the context of a framework that already provides validation conventions (as shown in MVC's Part 6: Using Data Annotations for Model Validation).
I'd go for something as the following.
public int Days
{
get => _days;
private set {
Ensure(1,7);
_days = value;
}
}
private void Ensure(int min, int max, [System.Runtime.CompilerServices.CallerMemberName] string memberName)
{
if (_min < value)
throw new ArgumentExcpetion($"'{memberName}' must be equal or greater than {min}.");
if (value < max)
throw new ArgumentExcpetion($"'{memberName}' must be equal or smaller than {max}.");
}
(Please note I adjusted <= and >= to match the error messages.)
With #rzmoz hint it was so easy:
Install PostSharp Tools for Visual Studio
Add NuGet packages
PostSharp.Patterns.Model with the RangeAttribute
PostSharp with the code weaving compiler
Apply the RangeAttribute to the property
[Range(1, 7)]
public int SanityCheckPeriod { get; internal set; }
Compile the stuff and everything works as expected
Tip: the property cannot be read-only and with private setter modifier R# complains Auto-property can be made get-only and recommends to remove it. But then the weaving will not work. Instead of suppressing this hint I switched to internal modifier which will not produce that R# hint.

C# error message "Property can not be assigned to -- it is read only."

Read only properties can be assigned in a constructor. But when I try to explicitly implement get method, compiler shows an error (Property cannot be assigned to -- it is read only.) Can I implement getter or it's supposed to be without implementation?
public class PersonalIncome
{
private decimal _anualRate;
public decimal AnualRate
{
get { return _anualRate != 0 ? _anualRate : 40_000; }
}
public PersonalIncome(decimal paymentRate)
{
switch (paymentRate)
{
case var rate when (rate > 300):
AnualRate = rate; // **Property can not be assigned to -- it is read only.**
break;
default:
break;
}
}
}
You can implement the getter, but then you can only assign values to the backing field directly:
_anualRate = rate;
Once you decide against using the convenience of the auto-property, you have to do everything by yourself.
Your class could be rewritten like this:
public class PersonalIncome
{
public decimal AnualRate { get; private set; }
public PersonalIncome(decimal paymentRate)
{
AnualRate = paymentRate > 300 ? paymentRate : 40_000;
}
}
You refer to a property with a readonly backing-field.
That´s exactly what the compiler also generates from C#6 upwards when using an auto-implemented property with a default-value:
int MyProperty { get; } = -1;
This will be translated to the following:
readonly int _myProperty = -1;
int MyProperty { get { return this._myProperty; } }
Now the compiler replaces every call to your property by the backing-field. However this only works for auto-properties that do not have a body defined. In your case you already have one, which is why the compiler can´t replace that one. As a property itself is nothing but a get- and a set-method, what you want to do is the following, which is obvious non-sense:
int get_MyProperty() { return this._MyProperty; }
...
this.get_MyProperty() = 1;
The reason this works for an auto-property is that the compiler knows how to replace the call to the property. However suppose your own getter was more complex:
get
{
DoSomething();
return this._myProperty + 5;
}
Now the compiler can´t replace the call to the property.
So the only way to have your own get-implementation tigether with a property which is get-only, is to use the backing-field:
this._myProperty = 1;

Check if object is defined after initialization in c#

I have the following object (class).
namespace Temp.Models
{
public class CurrentClass
{
private double _firstCoefficient;
private double _secondCoefficient;
public double FirstCoefficient
{
get { return _firstCoefficient; }
set { _firstCoefficient= value; }
}
public double SecondCoefficient
{
get { return _secondCoefficient; }
set { _secondCoefficient= value; }
}
}
}
The following class utilizes the above object and therefore initializes the object as follows:
namespace Temp.Models
{
public class MainClass
{
private CurrentClass _currentClass = new CurrentClass();
public CurrentClass CurrentClass
{
get { return _currentClass; }
set { _currentClass = value; }
}
}
}
At some point if certain conditions are met I would define the variables as follows:
MainClass currentObject = new MainClass();
//if conditions are met
currentObject.CurrentClass.FirstCoefficient = 0;
currentObject.CurrentClass.SecondCoefficient = 5;
But what if the conditions are never met and I never define the above variables. How and/or what is the best way to check if the object was never defined?
I can do the following check:
if(currentObject.CurrentClass.FirstCoefficient != 0 && currentObject.CurrentClass.SecondCoefficent != 0)
But the values can be defined as 0...So I am not sure how to go about this.
Any help is much appreciated!
These are some principles that can be used for solving the problem with description, samples and brief evaluation/opinion.
1. Parametrization through constructors
According to OOP principles, a constructor is method used to initialize an object to a valid state. The concept of immutability takes this even further, disallowing any changes, completely avoiding invalid state.
There is also a possibility of compromise where the API of an object disallows invalid states.
With this concept, you would arrive to:
namespace Temp.Models
{
public class CurrentClass
{
public double FirstCoefficient { get; private set; }
public double SecondCoefficient { get; private set; }
public CurrentClass(double firstCoefficient, double secondCoefficient)
{
FirstCoefficient = firstCoefficient;
SecondCoefficient = secondCoefficient;
}
// if mutability is required - this is needless as the constructor is
// the same but if there was more complex state, methods like this would make
// sense, mutating only parts of the state
public void SetCoefficients(double firstCoefficient, double secondCoefficient)
{
FirstCoefficient = firstCoefficient;
SecondCoefficient = secondCoefficient;
}
}
}
Summary:
Each instantiation of CurrentClass is always in a valid state, avoiding a lot of consistency checks (improved encapsulation)
It takes more code to write (but you save a lot of other code due to the previous point)
You need to know the coefficients beforehand.
2. Using nullable types
Nullable types add the "additional" value to types, the "undefined" state. Reference types (class) are nullable by design while value types (struct) need to be marked nullable, either as Nullable<T> or with the shorthand T?.
This then allows the objects be in invalid state and be specific about it. This goes to the other end of consistency scale from immutability as an object with multiple nullable fields has many invalid states.
Sample code:
namespace Temp.Models
{
public class CurrentClass
{
public double? FirstCoefficient { get; set; }
public double? SecondCoefficient { get; set; }
}
}
Now this gets instantiated quite nicely and can be changed on the fly:
public CurrentClass CreateCurrentClass()
{
var currentClass = new CurrentClass { FirstCoefficient = 1.0 };
var secondCoefficient = RetrieveSecondCoefficient();
currentClass.SecondCoefficient = secondCoefficient;
return currentClass;
}
You'll however need validity checks everywhere the object is used.
public bool IsValid(CurrentClass currentClass)
{
// what if FirstCoefficient has value and SecondCoefficient doesn't,
// is that always an invalid state?
return currentClass.FirstCoefficient.HasValue
&& currentClass.SecondCoefficient.HasValue;
}
Summary:
Very little code is needed to have a DTO up and running
A lot of consistency checks (and related brain pain) are required to work with such model
Encapsulation is lacking - any method taking CurrentClass can alter its validity, therefore making the previous point even worse. This can be eased by usage of read-only interface passed where read-only access is required.
Summing up
There are many other means that usually lay in between the two aforementioned approaches. For example you can use one validity flag (SergeyS's response) per object and ease on the external validity checks but having more code in the class and the need of deeper thinking.
Personally, I prefer immutability. It's more monkey code to write but will definitely pay off down the road thanks to the clean design.
A complex system without immutability is very hard to reason about without extensive knowledge. This is especially painful when working in a team - usually each person only knows a part of the codebase.
The sad thing is that it's not always possible to have evertything immutable (e.g. viewmodels): then I tend to convert objects to an internal immutable model as soon as it's possible.
Given what you already wrote, I would add Initialize() method and Initialized property into your MainClass class. Something similar to this:
public class MainClass
{
private CurrentClass _currentClass = new CurrentClass();
public CurrentClass CurrentClass
{
get { return _currentClass; }
set { _currentClass = value; }
}
public bool Initialized {get; private set;}
public void Initialize()
{
this.CurrentClass.FirstCoefficient = 0;
this.CurrentClass.SecondCoefficient = 5;
this.Initialized = true;
}
}
Call Initialize() method where your conditions met.
Later in code you can just check if(currentObject.Initialized). Notice private setter for `Initialized' property, it will ensure this flag was not accidentally set by external code.
Depending on your needs, you can go further and pass parameters for initialization directly to Initialize() method as parameters.
You have several approaches, like force values to be correct in constructor or have another variable telling if object has no value yet, like System.Drawing.Point has static "Empty" property. But in this case of your simple object your main class is explicitly creating an instance of CurrentClass so at this point this object should be correct and coefficients should be set. If you rely on some other code to set those values to perform some other action later, it is out of scope of these two objects here.
Update: perharps sharing details of what the real problem is would be better, because I have a feeling trying to provide a simpified example ended up in hiding real problem.

how can i get the value of another variable in C#

I am trying to write some code in C# with unity where i have an object who's position I need to know for my script to work. I was trying to use a pointer as that's what I thought was used. It said i had to use an unsafe tag which made me think i was doing something wrong. I am a little new to this and so far i have most of my knowledge with C++ as that's what i have learned in class. I tried looking it up but i could not find it. this is basically what i have right now.
using UnityEngine;
using System.Collections;
public class SGravSim : MonoBehaviour {
public GameObject moon;
public GameObject earth;
private struct Cords
{
public float* x
{
get
{
return x;
}
set
{
if (value != 0) <== this thing is realy just a placeholder
x = value;
}
}
public float* y
{
get
{
return y;
}
set
{
if (value != 0) <== this this is only in here for now
y = value;
}
}
public void DisplayX()
{
}
}
private Cords moonLocation;
private Cords earthLocation;
private Cords SataliteLocation;
// Use this for initialization
void Start () {
moonLocation.x = moon.transform.position.x;
moonLocation.y = moon.transform.position.y;
earthLocation.x = earth.transform.position.x;
earthLocation.y = earth.transform.position.y;
SataliteLocation.x = this.transform.position.x;
SataliteLocation.y = this.transform.position.y;
}
// Update is called once per frame
void Update () {
Debug.Log(moon.transform.position.x);
//
// Summary:
// The position of the transform in world space.
float yMoon = moon.transform.position.x
print(moonLocation.y);
}
}
I was planing on making the set so that you could not add anything to it.
I guess I could write out the whole earth.position.x thing every time I need to use it I was just trying to see if there was a better way to do it and also a way where I cant mess with the variable as all I want to do is read it.
You can use private set in the automatic properties :
public float X {get; private set;}
This way only your class will be able to set the variable but any other class wouldn't.
You shouldn't use pointers in c# except for really specific cases.
The solution several people gave you here is good:
public float X {get; private set;}
It is called a property and is one of the nice possibilities in c# to avoid creating getters and setters.
You say you have some knowledge in c++, but c# is actually closer to higher languages such as java. You should focus on the Object Oriented way to code and forget about low level pointers, especially using Unity.
You can use:
private float x;
public float X
{
get
{
return x;
}
}
Now you only set x from within your class.
You get the unsafe tag warning, because you try to use pointers, which are actually unsafe. There might be use-cases for that, but in C# you generally use reference types and value types. In C# a struct is a value type, so it will behave differently compared to a reference type, as you can read here, which is also why Gubr has suggested to use a class instead of a struct. Last but not least, there is a difference in how they are stored, just google C# heap and stack.
I haven't used structs that much in C# yet, so I just created a new project and played a bit around.
So I used your code, which also could just look like this:
private struct Cords
{
public float x, y;
public void DisplayX(){}
}
As the others have mentioned, you could leave out the set or make it private and add a constructor. Mind you, a private set doesn't equal to not defining it in auto-properties. Instead, it will create a readonly field. However, you have to call the new operator in both cases to set the value:
private struct Cords
{
public float X { get; }
public float Y { get; }
public void DisplayX(){}
public Cords(float x, float y)
{
X = x;
Y = y;
}
}
And here we create a new Cords:
Cords earth = new Cords(10.005f, 12.689f);

Does C#/CLR contain a mechanism for marking the return values of properties as read-only / immutable?

I've been looking around, and so far haven't managed to find a good way to do this. It's a common problem, I'm sure.
Suppose I have the following:
class SomeClass : IComparable
{
private int myVal;
public int MyVal
{
get { return myVal; }
set { myVal = value; }
}
public int CompareTo(object other) { /* implementation here */ }
}
class SortedCollection<T>
{
private T[] data;
public T Top { get { return data[0]; } }
/* rest of implementation here */
}
The idea being, I'm going to implement a binary heap, and rather than only support Insert() and DeleteMin() operations, I want to support "peeking" at the highest (or lowest, as the case may be) priority value on the stack. Never did like Heisenberg, and that whole "you can't look at things without changing them" Uncertainty Principle. Rubbish!
The problem, clearly, is that the above provides no means to prevent calling code from modifying MyVal (assuming SortedCollection) via the Top property, which operation has the distinct possibility of putting my heap in the wrong order. Is there any way to prevent modifications from being applied to the internal elements of the heap via the Top property? Or do I just use the code with a warning: "Only stable if you don't modify any instances between the time they're inserted and dequeue'd. YMMV."
To answer your question: No, there's no way to implement the kind of behavior you want - as long as T is of reference type (and possibly even with some value-types)
You can't really do much about it. As long as you provide a getter, calling code can modify the internal contents of your data depending on the accessibility of said data (i.e. on properties, fields, and methods).
class SomeClass : IComparable
{
private int myVal;
public int MyVal
{
get { return myVal; }
set { myVal = value; }
}
public int CompareTo(object other) { /* implementation here */ }
}
class SortedCollection<T>
{
private T[] data;
public T Top { get { return data[0]; } }
/* rest of implementation here */
}
//..
// calling code
SortedCollection<SomeClass> col;
col.Top.MyVal = 500; // you can't really prevent this
NOTE What I mean is you can't really prevent it in the case of classes that you don't control. In the example, like others have stated you can make MyVal's set private or omit it; but since SortedColleciton is a generic class, you can't do anything about other people's structures..
You can have a readonly property (that is, a property with only a getter):
private int myVal;
public int MyVal { get { return myVal; } }
But be careful: this may not always work how you expect. Consider:
private List<int> myVals;
public List<int> MyVals { get { return myVals; } }
In this case, you can't change which List the class uses, but you can still call that List's .Add(), .Remove(), etc methods.
Your properties don't have to have the same accessibility for get/set. This covers you for anything that returns a value type (typically structs that only contain value types) or immutable reference types.
public int MyVal
{
get { return myVal; }
private set { myVal = value; }
}
For mutable reference types, you have other options, such as returning Clone()s or using ReadOnlyCollection<T> to keep the caller from changing them:
private List<int> data;
public IList<int> Data
{
get { return new ReadOnlyCollection<int>(this.data); }
}
Only implement getters for your properties and modify the collection by having add/remove methods
I understand your problem now. I think this should work:
class SortedCollection<T> where T: ICloneable
{
private T[] data;
public T Top
{
get
{
T ret = (T)data[0].Clone();
return ret;
}
}
/* rest of implementation here */
}
The ICloneable constraint ensures that the type parameter implements the ICloneable interface. (if this is acceptable)

Categories

Resources