In C# I'm writing a class that checks the values of its properties with a setter method:
private int _grade
public int Grade {
get { return _grade;}
set { if (value >= this.lowerLimit) _grade = value; }
}
I would like to signal to the application if a value was rejected. I had considered refactoring to use a setGrade function that returns a bool (accepted / rejected) but the ability to do someInstance.Grade++ and someInstance.Grade*=2 are important. Simple functions incrementGrade and divideGrade will make the code a mess, and there will certainly be some function that I forgot to implement (too much coupling).
My current solution is to check the value of someInstance.Grade after setting it, to ensure that it has been set. But it seems to me that this is just moving the mess from the class to the application. Indeed, it is the responsibility of the application to ensure that the value was properly set.
How do those more experienced handle this? Thanks!
It is indeed caller's responsibility to set values that make sense.
Normally, it is accepted practice to throw ArgumentOutOfRangeException in the setter when the value is wrong. If the caller expects possibly wrong value (e.g. user input), it can catch the right exception.
private int _grade
public int Grade {
get { return _grade;}
set {
if (value < lowerLimit) {
throw new ArgumentOutOfRangeException("value",
string.Format("Grade must be higher than or equal to {0}.", lowerLimit)
);
}
_grade = value; // will not happen if the exception was thrown
}
}
There is also ArgumentNullException for null values when you don't want them, and general ArgumentException if your argument rejection reason is different from these two cases.
A more hip approach would be to use Code Contracts as suggested by Jean-Bernard.
However this feature is still somewhat new and not widely used in .NET projects.
Code Contracts add static analysis so you discover such errors at compilation stage.
They will still throw ArgumentExceptions in runtime, though.
You could use Code Contracts
Here is an answer to another question which has more resources: link
Most of the time, I either silently adjust the value given to be within the range of values, or throw an Exception, depending on the situation.
Another option: you could make an event PropertyValueRejected that your class's clients could subscribe to:
public class PropertyValueRejectedEventArgs {
public string PropertyName { get; set; }
public object RejectedValue { get; set; }
}
public class MyClass {
public event EventHandler<PropertyValueRejectedEventArgs> PropertyRejected;
private int _grade = -1;
public int Grade {
get { return _grade; }
set {
if (value >= this.lowerLimit) {
_grade = value;
}
else if (PropertyRejected != null) {
PropertyRejected(
this,
new PropertyValueRejectedEventArgs {
PropertyName = "Grade",
RejectedValue = value
}
);
}
}
}
}
Related
My lecturer told us to use private fields and public properties. Recently, I was watching a tutorial video. The presenter only created properties. Is it ok to just use the property?
Public properties such as
public string Name { get; set; }
automatically implement private backing fields by the compiler. You never see them, but the effect is the same as manually specified backing fields.
private string name;
public string Name { get { return name; } set { name =value; } }
For .Net framework 2.0 and less, private fields are necessary, otherwise you will get compile errors.
In higher versions of .Net Framework, it will work fine without any errors.
Using private fields has many advantages
Validating the inputs before assigning them to the properties
public int Max
{
get { return m_Max; }
set
{
if (value>0 && value<100)
{
m_Max=value;
}
}
}
Triggering exceptions for incorrect values
From https://msdn.microsoft.com/en-us/library/ms229006.aspx,
preserve the previous value if a property setter throws an exception.
AVOID throwing exceptions from property getters. If a getter can throw
an exception, it should probably be redesigned to be a method
public int Max
{
get { return m_Max; }
set {
if(value > 0 && value < 100){ \\Value is within valid range
m_Max = value;
}
else if(value < 0)
//throw some exception to indicate value is not valid
else if(value > 100)
//throw some exception to indicate value is not valid
}
}
Yes it's okay to use public properties without private fields, though just using public fields is not okay. The reason for this is with properties you have the ability to change how you validate and store the field internally later on, whereas with just public fields changing would break any users of your class. The key difference is that with properties you still have control of the internal state of the class, even if that's with auto generated fields, whereas with public fields you don't.
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.
I have seen two ways of doing data validation in .Net 4.0.Currently Iam using IDataErrorInfo like this but the problem here is "this" of IDataErrorInfo is called only when getter of Age property is called.I have some logic in the setter which is dependent on valid value of Age.
public int Age
{
get { return _age; }
set
{
_age = value;
OnPropertyChanged("Age");
//My methods to call when Age is valid
}
}
public string this[string columnName]
{
get
{
string error = null;
switch (columnName)
{
case "Age":
if (Age < 10 || Age > 100)
error="The age must be between 10 and 100";
break;
}
return error;
}
}
I can't call those methods as validation is not done when setter is called ,its done only when getter is called.Can somebody help me understand why its designed like that.In my opinion validation should be close to setter where value is assigned.
I am bound to change my implementation to this ,using Exception validation
public int Age
{
get { return _age; }
set
{
if (value < 10 || value > 100)
throw new ArgumentException("The age must be between 10 and 100");
_age = value;
//My methods to call when Age is valid
}
}
I am asking this question because the existing implementation is based on IDataErrorInfo in my project and there are lot of properties getting validated.Is there some solution which will let me keep IDataerrorInfo implementation and achieve the same I achieve from doing exception validation.
I do not want to throw exception on my property setters because its a design guideline by microsoft
Do not use exceptions for normal flow of control, if possible. Except
for system failures and operations with potential race conditions,
framework designers should design APIs so that users can write code
that does not throw exceptions. For example, you can provide a way to
check preconditions before calling a member so that users can write
code that does not throw exceptions.
and also I don't want to throw exceptions which I do not catch in my viewmodel code only.
This is my xaml
<TextBox Text="{Binding Age, ValidatesOnDataErrors=True,
NotifyOnValidationError=True, ValidatesOnExceptions=True,
UpdateSourceTrigger=PropertyChanged}"/>
Binding first sets the value and then it calls the getter aaand then indexer is being called to validate. However your issue is that you wish the indexer to come first. That is not how wpf works.
Basically wpf gives you all freedom when using IDataErrorInfo therefore you have to implement all by yourself. Let me show you just an example:
public int Age
{
get { return _age; }
set
{
int oldVal = _age;
_age = value;
if(Validate("Age") == null)
{
// Do whatever you want
OnPropertyChanged("Age");
}
else
{
// You can rollback value or not, it wouldnt matter...
// PropertyChanged will not be fired!!!
_age = oldVal;
}
}
}
public string this[string columnName]
{
get
{
return Validate(columnName);
}
}
public string Validate(string propertyName)
{
string error = null;
switch (propertyName)
{
case "Age":
if (_age< 10 || _age > 100)
error = "The age must be between 10 and 100";
}
return error;
}
In my opinion, best way to achieve that is to call checking method in a setter and if it's validation result is false, don't set value to property and set some "InvalidState" flag. Otherwise set value and continue.
With InvalidState flag, you can throw InvalidOperationException when any method depending on object's state is called.
You can use basic Boolean value InvalidState or not or you can use Enum with different states (NotInitialized, Valid, Invalid, etc.) to manage code flow.
The issue here is due to your design rather than anything being done in .NET or by WPF.
From the sounds of it, you are immediately updating something based on the OnPropertyChanged() call in your code. I would not do this when working with UI-bound elements where users are involved as humans are the weak point in any system and you are always going to get invalid input from a user at some point.
You should rather be doing a deterministic update via a Save Command rather than a continuous update based on OnPropertyChanged(). The point of form validation is that you can deterministically validate an entire set of data before committing it to an underlying structure.
You should rather do something like add a private Boolean variable to store the validation state of the Age property and enable/disable the Save Command via the ICommand.CanExecute() method.
I have a class that looks the following way:
public class StackOverflowQuestion {
private string _question;
public string Question {
get { return _question; }
set { _question = value; }
}
public StackOverflowQuestion(string question) {
_question = question;
}
public override string ToString() {
return _question;
}
}
Now, the value "question" isn't allowed to be null or empty and the user should be notified via a ArgumentNullException - but where should it been thrown? According to the 'fail-fast' principle -> Everywhere.
public class StackOverflowQuestion {
private string _question;
public string Question {
get { return _question; }
set {
if(!String.IsNullOrEmpty(value))
_question = value
else throw new ArgumentNullException("value");
}
}
public StackOverflowQuestion(string question) {
if(!String.IsNullOrEmpty(question))
_question = question;
else throw new ArgumentNullException("question");
}
public override string ToString() {
if(!String.IsNullOrEmpty(_question)) return _question;
else throw new ArgumentNullException("_question");
}
}
Now this is obviously ridiculous and extremely repetitive. But it seems right: If the value is set through .ctor, it fails directly after a short check. When its set through the property, it fails directly after a short check.. but who expects exceptions on a setter? And when I output the string, I expect a string, not an exception for something that should have happend long ago, but again: If it's wrong, it should fail ASAP, even if 'soon' is quite late.
So, where should the only exception handling been done? Am I asking for a 'best-practice', or is this a taste thing?
Since _question is private, there's no need to check whether it is null in ToString() (unless you're just sanity checking your own code).
You can avoid the check in the constructor by having the constructor use the property setter. Thus, I'd recommend:
public class StackOverflowQuestion {
private string _question;
public string Question {
get { return _question; }
set {
if(string.IsNullOrEmpty(value))
// to make this more transparent when thrown through the constructor, it might
// be preferable to throw a real error message like "Question: cannot be null or empty"
throw new ArgumentException("value");
this._question = value;
}
}
public StackOverflowQuestion(string question) {
this.Question = question;
}
public override string ToString() {
return this.Question;
}
}
A few things to note:
1. You should throw ArgumentException rather than ArgumentNullException for empty strings (if you want you can do 2 checks and still throw ArgumentNullException for nulls).
2. While the approach uses less code, the one disadvantage is that the error message users get is slightly worse than when they pass null to the constructor, since the failure happens 2 levels deep instead of one.
You only need to test it once - in the single place where you set the variable, having changed the constructor to use the property:
public class StackOverflowQuestion
{
private string _question;
public string Question
{
get { return _question; }
set
{
if (String.IsNullOrEmpty(value))
{
throw new ArgumentException("Question cannot be null or empty",
"value");
}
_question = value;
}
}
public StackOverflowQuestion(string question)
{
Question = question;
}
public override string ToString()
{
return Question;
}
}
The one downside here is that the "bad parameter" name will be value rather than question when it's null in the constructor, but I think that's a price worth paying. An alternative is just to use the message, and not specify the parameter name.
You may want to separate out null from empty, so that you can throw an ArgumentNullException when it's null - but you shouldn't be throwing ArgumentNullException when it's just empty.
You don't need to perform any checks when fetching the value, as you know it will never be null or empty, because you're preventing it from ever being set that way.
You should also consider whether you could make the class immutable, at which point you'd only need to test in the constructor as there wouldn't be a setter...
I would rather make it immutable:
public class StackOverflowQuestion
{
public string Question
{
get; private set;
}
public StackOverflowQuestion(string question)
{
if (String.IsNullOrEmpty(question))
throw new ArgumentNullException("question");
Question = question;
}
public override string ToString()
{
return Question;
}
}
The C# "readonly" keyword is a modifier that when a field declaration includes it, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
Now suppose I do want this "assign value once" constraint, but I would rather allow the assignment be done outside of constructors, a lazy/late evaluation/initialization maybe.
How could I do that? and is it possible to do it in a nice way, for example, is it possible to write some attribute to describe this?
If I understand your question correctly, it sounds like you just want to set a field's value once (the first time), and not allow it to be set after that. If that is so, then all the previous posts about using Lazy (and related) may be useful. But if you don't want to use those suggestions, perhaps you can do something like this:
public class SetOnce<T>
{
private T mySetOnceField;
private bool isSet;
// used to determine if the value for
// this SetOnce object has already been set.
public bool IsSet
{
get { return isSet; }
}
// return true if this is the initial set,
// return false if this is after the initial set.
// alternatively, you could make it be a void method
// which would throw an exception upon any invocation after the first.
public bool SetValue(T value)
{
// or you can make thread-safe with a lock..
if (IsSet)
{
return false; // or throw exception.
}
else
{
mySetOnceField = value;
return isSet = true;
}
}
public T GetValue()
{
// returns default value of T if not set.
// Or, check if not IsSet, throw exception.
return mySetOnceField;
}
} // end SetOnce
public class MyClass
{
private SetOnce<int> myReadonlyField = new SetOnce<int>();
public void DoSomething(int number)
{
// say this is where u want to FIRST set ur 'field'...
// u could check if it's been set before by it's return value (or catching the exception).
if (myReadOnlyField.SetValue(number))
{
// we just now initialized it for the first time...
// u could use the value: int myNumber = myReadOnlyField.GetValue();
}
else
{
// field has already been set before...
}
} // end DoSomething
} // end MyClass
Now suppose I do want this "assign value once" constraint, but I would rather allow the assignment be done outside of constructors
Note that lazy initialization is complicated, so for all of these answers you should be careful if you have multiple threads trying to access your object.
If you want to do this inside the class
You can use the C# 4.0 built-in lazy initialization features:
http://msdn.microsoft.com/en-us/library/dd997286.aspx
http://msdn.microsoft.com/en-us/library/dd642331.aspx
http://sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt/
Or for older versions of C#, just supply a get method, and check if you're already initialized by using a backing field:
public string SomeValue
{
get
{
// Note: Not thread safe...
if(someValue == null)
{
someValue = InitializeSomeValue(); // Todo: Implement
}
return someValue;
}
}
If you want to do this outside the class
You want Popsicle Immutability:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx
http://msdn.microsoft.com/en-us/library/ms750509.aspx
http://csharpindepth.com/Talks.aspx (search for "popsicle immutability" and you'll find a video)
Basically:
You make the whole class writable, but add a Freeze method.
Once this freeze method is called, if users try to call setters or mutator methods on your class, you throw a ModifyFrozenObjectException.
You probably want a way for external classes to determine if your class IsFrozen.
BTW, I made up these names just now. My selections are admittedly poor, but there is no generically followed convention for this yet.
For now I'd recommend you create an IFreezable interface, and possibly related exceptions, so you don't have to depend on the WPF implementation. Something like:
public interface IFreezable
{
void Freeze();
bool IsFrozen { get; }
}
You can use the Lazy<T> class:
private readonly Lazy<Foo> _foo = new Lazy<Foo>(GetFoo);
public Foo Foo
{
get { return _foo.Value; }
}
private static Foo GetFoo()
{
// somehow create a Foo...
}
GetFoo will only be called the first time you call the Foo property.
This is know as the "once" feature in Eiffel. It is a major oversight in C#. The new Lazy type is a poor substitute since it is not interchangeable with its non-lazy version but instead requires you to access the contained value through its Value property. Consequently, I rarely use it. Noise is one of the biggest problems with C# code. Ideally, one wants something like this...
public once Type PropertyName { get { /* generate and return value */ } }
as oppose to the current best practice...
Type _PropertyName; //where type is a class or nullable structure
public Type PropertyName
{
get
{
if (_PropertyName == null)
_PropertyName = /* generate and return value */
return _PropertyName
}
}