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.
Related
Hey Guys i could need some Help here.
I'm supposed to implement an abstract class with some attributes (that I already have). Now I'm supposed to write a constructor that initializes the attributes and add getters and setters. Here I am stuck can someone tell me how to implement this?
Here is my abstract class
namespace Personalverwaltung {
public abstract class Person
{
public string Name;
public string Adresse;
public int Hausnummer;
public int PLZ;
public string Ort;
}
}
There are no Getters and Setters in C# (at least they are not advised as in i.e. Java implementations), there are only properties.
Take a look here to help you: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
Example:
private double _seconds;
public double Hours
{
get { return _seconds / 3600; }
set {
if (value < 0 || value > 24)
throw new ArgumentOutOfRangeException(
$"{nameof(value)} must be between 0 and 24.");
_seconds = value * 3600;
}
}
For an example constructor, look here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/constructors
Both articles will help you learn when you implement them. There are enough examples and information to get you going. Good luck on your programming journey.
This question already has answers here:
Is it possible to have a getter for a const?
(4 answers)
Closed 5 years ago.
I am just wondering if I have a constant attribute, can I set a public property to encapsulate it?
e.g.
private const int DEFAULT_CHARGE = 200;
public int default_charge
{
get { return DEFAULT_CHARGE; }
}
I don't get any errors but if something is constant I don't really understand the logic of why we encapsulate it. I really want to understand why this is:
right/wrong
why do it?
benefits?
It's important to know that constants are inlined by the compiler. It means that these two examples result in the same program:
private const int DEFAULT_CHARGE = 200;
public int default_charge
{
get { return DEFAULT_CHARGE; }
}
Is the same as this, after compiling:
public int default_charge
{
get { return 200; }
}
As you can see, the reference to DEFAULT_CHARGE is lost after compiling. That is important to remember for solutions where you reuse the same constants in multiple projects.
Let's say you use DEFAULT_CHARGE as a public const in LibA and LibB. Your project manager tells you to change the value from 200 to 300. Instinctively, you go to LibA where DEFAULT_CHARGE is defined, you change it to 300 and then you re-compile and deploy only LibA.
The result is that LibA now uses the new value of 300 but LibB keeps using the old value of 200, because the constant was baked into the DLL at compile-time.
The reason why you might encapsulate the constant is so that you can more easily change the value. Requirements tend to change over time. A DEFAULT_CHARGE value that is constant today might have to be replaced by a configuration value in the future.
By encapsulating the constant, you also prevent the problem that I just explained. If both LibA and LibB (and LibX, LibY,LibZ,...) depend on the encapsulation, you only need to recompile and deploy LibA to set the default charge in all dependent programs.
Even if something is constant you could still want control over how it is returned to the caller. If you have a have a Double variable that is store to 5 decimal places you could want to return the value to the caller in 2 decimal places. Encapsulation helps you get this control over your fields.
So you might need to encapsulate a constant field like this
private const double DEFAULT_CHARGE = 200.12345;
public int default_charge
{
get { return Math.round(DEFAULT_CHARGE,2); }
}
You may want to implement interface, abstract class etc.:
public interface IChargable {
int default_charge {get;}
}
public class MySimpleChargable: IChargable {
private const int DEFAULT_CHARGE = 200;
public int default_charge {get { return DEFAULT_CHARGE; }}
}
You may implement such a construction as a stub:
Initial:
// Version 1.0
public class MyChargable {
private const int DEFAULT_CHARGE = 200;
//TODO: implement (rare) "some condition" case
public int default_charge {get { return DEFAULT_CHARGE; }}
}
Later:
// Version 1.1
public class MyChargable {
private const int DEFAULT_CHARGE = 200;
public int default_charge {
get {
if (some condition)
return SomeComputation();
return DEFAULT_CHARGE;
}
}
It depends on your requirements.
In general, properties are designed to encapsulate any getting / setting logic you want, even calculable values or constants.
In my opinion, public property returning a value of a private constant is good in terms of architecture, in this case someone who uses your code doesn't know that he works with constant at all, i.e. he is abstracted from your implementation, and that's good. If you decide to make it not a constant, but configurable value, then you wouldn't expose it to your library consumer, you just make it like:
// private const int DEFAULT_CHARGE = 200; <-- is not used anymore
public int DefaultCharge
{
get { return SomeSortOfFileOrDatabaseConfiguration.DefaultCharge; }
}
or even
public int DefaultCharge
{
get
{
return CurrentUser.PersonalSettings.DefaultCharge;
}
}
which makes this code rely on users' personal settings without telling anything to your clients.
That's the main benefit. It is all about encapsulation and abstraction.
But please use proper naming for properties - it should be public int DefaultCharge, and pay attention to Jeroen Mostert's comment about constant inlining.
To my knowledge, you can create an public accessor to a private constant no problems.
You should create an accessor to a constant when:
You need to add extra logic to a getter like return it formated in some way or other value if a condition applies.
Your constant is part of a namespace that is used as library for other namespace, since if you compile the namespace on which the constant exists, the dependant namespace will only remember the old value of the constant, as it was defined on compilation.
I encountered this FxCop rule before and wasn't really content with how to solve violations (thread1, thread2). I now have another case where I need to correct violations of the CA1819 kind.
Specifically, I have an algorithm-library that performs some analytic calculations on a curve (x,y), with a public "input object" like this:
public class InputObject
{
public double[] X { get; set; }
public double[] Y { get; set; }
// + lots of other things well
}
This object's X and Y properties are used in hundreds of locations within library, typically using indexes. The input object is never altered by the algorithms, but actually it shouldn't matter if so. Also, .Length is called pretty frequently. It's a mathematical library, and double[] is kind of the standard data type in there. In any case, fixing CA1819 will require quite some work.
I thought about using List<double>, since Lists support indexing and are quite similar to arrays but I'm not sure whether this may slow down the algorithms or whether FxCop will be happy with those Lists.
What is the best option to replace these double[] properties?
If it is read only to external consumer and consumer does not want to access it by index then the best is to have a public read only property of type IEnumerable<> with method accessors to add and remove, this way you will not have to expose your array to someone to mess with.
If you need to access the indexers then expose it as read only property of type IList<> and probably return a ReadOnly instance, with methods to add and remove.
This way you keep encapsulation of the internal list and allow consumer to access it in a read only way
Sometime FxCop from my point of view exagerates.
It all depends on what you have to do, if you are writing a complex system where security and very clean code is required, you should returns a readonly version of that array.
That is, cast the array as IEnumerable as suggests devdigital or use the good idea ImmutableArray of Mohamed Abed, that i prefer.
If your are writing software that require high performance... there is nothing better than an array for performances in C#.
Arrays can be a lot more performant for iterating and reading.
If performances are really important I suggest you to ignore that warning.
Is still legal, also if not too much clean, to return a readonly array.
for (int i = 0; i < array.Length; ++i) { k = array[i] + 1; }
This is very fast for big arrays in C#: it avoids array bounds check.
It will perform very much as a C compiled code would do.
I always wished a "readonly array" type in C# :) but there is no hope to see it.
As your link suggests:
To fix a violation of this rule, either make the property a method or
change the property to return a collection.
Using a collection such as a List should not have a significant impact on performance.
The big problem here isn't really what your library does with the values (which is a potential problem, albeit a much more manageable one), but rather what callers might do with the values. If you need to treat them as immutable, then you need to ensure that a library consumer cannot change the contents after their original assignment. The easy fix here would be to create an interface that exposes all the array members that your library uses, then create an immutable wrapper class for an array that implements this interface to use in your InputObject class. e.g.:
public interface IArray<T>
{
int Length { get; }
T this[int index] { get; }
}
internal sealed class ImmutableArray<T> : IArray<T>
where T : struct
{
private readonly T[] _wrappedArray;
internal ImmutableArray(IEnumerable<T> data)
{
this._wrappedArray = data.ToArray();
}
public int Length
{
get { return this._wrappedArray.Length; }
}
public T this[int index]
{
get { return this._wrappedArray[index]; }
}
}
public class InputObject
{
private readonly IArray<double> _x;
private readonly IArray<double> _y;
public InputObject(double[] x, double[] y)
{
this._x = new ImmutableArray<double>(x);
this._y = new ImmutableArray<double>(y);
}
public IArray<double> X
{
get { return this._x; }
}
public IArray<double> Y
{
get { return this._y; }
}
//...
}
The elements in your "immutable" array contents would still be mutable if T is mutable, but at least you're safe for the double type.
Change array [] to IEnumerable:
public class InputObject
{
public IEnumerable<double> X { get; set; }
public IEnumerable<double> Y { get; set; }
// + lots of other things well
}
Trying to decipher an appropriate OO design to implement. The basic scenario is that you have a PstnNumber which is essentially a 10 digit phone number that always starts with 0 (e.g. 0195550000). A rule has been introduced to allow auto-correcting of a number if the leading 0 is missing (e.g. 195550000).
START EDIT
I realised the original question may have been misunderstood (thankyou kindly to those whom have answered already), so I have edited to try and better explain the scenario.
END EDIT
I started playing with some preliminary concepts and then thought I would ask if there was a more appropriate way to go or do one of these suffice (on some level)?
Concept 1
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number)
{
this.Number = number;
}
}
public class AutoFormattedPstnNumber : PstnNumber
{
public override string Number
{
get { return base.Number; }
set { base.Number = value.PadLeft(10, '0'); }
}
public AutoFormattedPstnNumber() : base() { }
public AutoFormattedPstnNumber(string number)
{
this.Number = number;
}
}
Concept 2 (removed)
Concept 3
public class PstnNumber
{
public bool AutoCorrect { get; set; }
private string number;
public virtual string Number
{
get { return (this.AutoCorrect) ? this.number.PadLeft(10, '0') : this.number; }
set { this.number = value; }
}
public PstnNumber() : this(false) { }
public PstnNumber(bool autoCorrect)
{
this.AutoCorrect = autoCorrect;
}
public PstnNumber(string number) : this(false)
{
this.Number = number;
}
public PstnNumber(string number, bool autoCorrect) : this(autoCorrect)
{
this.Number = number;
}
}
I think Concept 1 may violate the Liskov Substitution rule because the subclass changes the behaviour of the Number property (happy to learn if I've misunderstood that).
Any alternative suggestions would be received happily.
do you have to do the autoformatting when the object is instantiated? If not,
what about:
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number) { this.Number = number; }
public AutoFormatNumber { get { return Numer.PadLeft(10, '0'); } }
}
avoid getter-setter-surprise
Avoid getters returning a different value than the one accepted by the setter. Imagine the following snippet:
if (input.Value != current.Number)
{
NumberChangedAgain = true;
current.Number = input.Value;
}
A simple solution would be to make PstnNumber immutable:
temp = PstnNumber.FromString(input.Value);
if (temp != current) { ... }
canonical format
If some data has different representations, there is a lot of advantage to storing it in a canonical representation, and move the format conversions to factory functions and getters / formatters. For example, you don't need to test comparison for short vs. long, long vs. short, short vs. short, long vs. long.
different aspects
Do you need the distinction between an "autoformatted" and a "normal" number, or is this merely a question of input and output - i.e.
does display format (short or long) depend on how the number was entered, or on where it is displayed?
is 0195550000 == 195550000 ?
I'd prefer to fold both classes into one if possible (i.e. when "entered with or without 0 can be forgotten"):
public class PstnNumber
{
private string m_number; // always in long format
public static PstnNumber(string s) { ... } // accepts short and long form
public string Number { get { return m_number; } }
public string AutoFormatted { { get { ... } }
}
Otherwise I'd go with Option 3, but always store the long format in m_number.
In Option 1 and Option 2, you aren't preserving the original number anyway, rendering the subclass worthless (except to know that it was autoformatted at some point, which doesn't seem like useful information). The alternative to make these Options more useful would be to format on Get instead of Set.
Option 3 is therefore the preferred pattern out of these three options, but I would also ask - why can't the PstnNumber also simply detect the number of digits, and autoformat accordingly?
If you follow the rules - there is one that says that "each routine (read class) should do only one thing and do it well".
According to that I would make PstnNumber just hold the number, and create some sort of factory that produces the right number.
Doing both in the same class means that you are weaving domain logic and representation. I prefer them separated.
I'd ask why your class name is so cryptic. "Number" is clear to me, and "P" suggests "phone", but what's the "stn" telling me? A few extra keystrokes would make this class more self-documenting.
I'd also ask about the logic of a default constructor that does not initialize the underlying data members to some value. I think a default constructor should have a sensible default value if possible.
I feel like option 1 is overkill. I don't think inheritance is making this model clearer or better. I don't see how it breaks Liskov substitution, which demands that you can use the subclass in any situation that calls for a base class. The methods map 1:1 as far as I can see. How is Liskov violated?
Option 2 says these are two separate classes with no relationship. That doesn't seem right to me.
All this work suggests that your problem will require that you use both classes. You'll have situations where the leading zero is NOT required and others where it is. Is that true? Or are you always going to require the leading zero?
I don't care for any of your options. I'd prefer an interface or a static factory or even modifying the class you have to anything you've suggested. It feels like a mere formatting issue. Do you store the number with the leading zero? If not, maybe it's just a view concern.
Do you have a really strong reason to have a setter and not have your members final? If not, that's probably a bigger problem than any other variation between the three.
So I'd go for a stateless #3 which means making the number final and gettng rid of the autoFormat variable.
For simplicity I'd just have a getNumberRaw and getNumberFormatted
Better yet, you could have getNumberRaw and getNumber(formatType) where formatType actually contains the code that formats the number since the format may change again in the future and combining formatting (view) with your phone number (model) isn't optimal.
(PS/EDIT): just the fact that a phone number can change is NOT a good reason to have a setter! Creating a new phone number object and replacing the old one will almost always work!
I am not familiar with c#, but I'd do this:
public class PstnNumber {
readonly string number;
public PstnNumber(string number) {
this.number = number;
}
public string getNumber() {
return number;
}
static public PstnNumber createNumber(string number) {
return new PstnNumber(number.PadLeft(10, '0'));
}
}
Of course if I knew how Properties work, I'd probably do it differently :)
I would go with a much simpler version, overriding the ToString method, or even, creating an ToString overload that receives the bool parameter indicating that the number should be formatted.
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.