Where should exceptions been thrown? - c#

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;
}
}

Related

Return Nothing in an if statement of a property's setter WPF

What is the flow of the below code snippet?
What does return; means?
What will it do when return; executes?
public bool ActionSafeAction
{
get
{
return this.ActionSafeAction;
}
set
{
if (value.Equals(this.ActionSafeAction))
{
return;
}
if (value)
{
this.ActivateItem(this.ActionSafeAction);
this.ActionSASelected = false;
}
this.ActionSafeAction= value;
this.NotifyOfPropertyChange(() => this.ActionSafeAction);
}
}
It will do nothing more of what comes after the return. It immediately returns from the setter and doesn't change any underlying value.
Writing ActionSafeAction = true if ActionSafeAction is already true will hit this return statement and not do anything more.
Properties are little more then Syntax Sugar for Get and Set functions. That is what they are designed to be.
Set in paritcular is effectively a function that takes a parameter "value" and returns void. Except for the name and the way you call it, that set is effectively: public void SetActionSafeAction(bool value). Making getters and setters easily implement and useable - again, that is what Properties are there for.
The return in the if will end the execution of this function, there and then. As it would with any other function that returns void. The rest of the checks and the setting/change notification will not be executed.
I think if we illistruate the getter and setter like below you may understand better. Get and Set are implict definition of two seperated method that effect a particular member.
public class Foo
{
private string myMember;
public string GetMyMember()
{
return myMeber;
}
public void SetMyMember(string value)
{
myMember = value;
}
}
So as you see setter is a actually a void method and when you call return statement at any part of this method it will just leave method without executing rest of the code. This is what happned at your ActionSafeAction propertiy's setter too.
The equal of the above two method will be this property:
public class Foo
{
private string myMember;
public string MyMember
{
get { return myMember; }
set { myMember = value; }
}
}

How to create a base class/struct for value objects that validates based on super class values?

this is a problem I'm not sure how to call it or how name the things I want to do but hopefully the code examples can speak for themselves. I come from a PHP background and am learning .NET Core 2.2/3.0. Something I'm running into right now though is how I can avoid some code duplication when creating similar classes. For example I want to create multiple value objects that basically just contain strings, but each value object has different constraints. In most cases however the only constraint differences are in the length.
So in PHP I would do something like this:
abstract class Text
{
abstract public static function maxCharacters(): int;
protected $value;
public function __construct(string $text)
{
if (mb_strlen($text) > static::maxCharacters()) {
throw new LengthException(sprintf('Too many characters, the max is %d.', static::maxCharacters()));
}
$this->value = $text;
}
public function value(): string
{
return $this->value;
}
}
class Name extends Text
{
public static function maxCharacters(): int
{
return 50;
}
}
class Description extends Text
{
public static function maxCharacters(): int
{
return 1000;
}
}
It's not the best example of inheritance, but the goal is to illustrate the point in that I would like to have 1 place where I can put my validation logic, and then in the subclass only have to define the parameters of the validation and not the actual logic to perform the validation.
Since we're dealing with value objects here I assume that in C# it would be best to use a (readonly) struct. So, without any inheritance, what I ended up with as the C# equivalent is:
public readonly struct Name
{
private const int MAX_CHARACTERS = 50;
public string Value
{
get { return this.Value; }
set
{
if (value.Length > Name.MAX_CHARACTERS)
{
throw new ArgumentOutOfRangeException(String.Format("Too many characters, the max is {0}.", Name.MAX_CHARACTERS));
}
this.Value = value;
}
}
public Name(string name) => this.Value = name;
}
public readonly struct Description
{
private const int MAX_CHARACTERS = 1000;
public string Value
{
get { return this.Value; }
set
{
if (value.Length > Description.MAX_CHARACTERS)
{
throw new ArgumentOutOfRangeException(String.Format("Too many characters, the max is {0}.", Description.MAX_CHARACTERS));
}
this.Value = value;
}
}
public Description(string description) => this.Value = description;
}
But as you can see without inheritance that's a lot of copy/paste, and copy/paste is something I prefer to avoid. The only alternative I could think of is to create a separate TextValidator class or something that I can call from the set to which I would only have to pass the max number of characters, but that would still leave me with more copy/paste than I'd prefer.
How would you write something like this in C# with as little copy/paste as possible?
It seems like you've got the basics of inheritance understood in your PHP example; I'd just suggest doing a bit of reading on the syntax in C#.
For what it's worth, the following would do the trick:
public abstract class Text{
public string Value { get; }
public Text(string val) {
if (val.Length > MAX) throw new Exception();
Value = val;
}
protected abstract int MAX{get;}
}
public class Name : Text{
public Name(string val): base(val) { }
protected override int MAX => 50;
}
public class Description : Text
{
public Description(string val) : base(val) { }
protected override int MAX => 1000;
}
I'll also add a footnote to say be careful calling abstract methods/properties from a class constructor (which is what I'm doing here). If, for example, the value of MAX is a computed value which depends on the object already having been initialized, you could run into some issues. In this case though, it won't be a problem.

C# default Write Property name

Is there any way to fast override the "value" name for a new variable that is placed in the set block in C#?
class Foo {
string name = "guy";
public string Name {
get {
return name;
}
set {
if (value != "foo") {
name = value;
} else {
Console.WriteLine("sorry I already took that one!");
}
}
}
For example in swift I could write it this way:
var Name: String {
get {
return name;
}
set (newName) {
if (newName == "Foo") {
print("sorry I already took that one!")
} else {
name = newName;
}
}
}
I know I can easily solve it by assignment at the beginning of the block but the approach with naming the value in parenthesis just after the keyword is very clear to me so just wanted to ask is there another solution.
Basically, no. It is a language feature that value is the contextual keyword that always represents the incoming value in a set accessor (and in custom event accessors).
You can fake it:
var newName = value;
but... you get better syntax highlighting with value than newName, and any C# reader automatically knows what value represents in that context.

Property never null c#

When refactoring code, I come up with instances like the following
private string _property = string.Empty;
public string Property
{
set { _property = value ?? string.Empty); }
}
Later on in a method I see the following:
if (_property != null)
{
//...
}
Assuming that _property is only set by the setter of Property, is this code redundant?
I.e is there any way, through reflection wizardry or other methods that _property can ever be null?
Assuming that _property is only set by the setter of Property, is this
code redundant?
Exactly, it is redundant. This is the actual purpose of Properties. We shouldn't access the fields of a class directly. We should access them using a Property. So in the corresponding setter, we can embed any logic and we can rest assure that each time we try to set a value this logic would be verified once more.This argument holds even for the methods of a class. In a method we must use the properties and not the actual fields. Furthermore, when we want to read the value of a field, we should make use of the corresponding getter.
In general, properties enhances the concept of encapsulation, which is one of the pillars of object oriented programming OOP.
Many times there isn't any logic that should be applied when we want to set a value. Take for instance the following example:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
We have declared a class for representing a Customer. A Customer object should have three properties an Id, a FirstName and a LastName.
An immediate question, when someones read this class is why should someone make use of properties here?
The answer is again the same, they provide a mechanism of encapsulation. But let's consider how can this help us in the long run. Let's say that one day someone decides that the first name of a customer should be a string of length less than 20. If the above class had been declared as below:
public class Customer
{
public int Id;
public string FirstName;
public string LastName;
}
then we should check for the length of FirstName in each instance we had created ! Otherwise, if we had picked the declaration with the properties, we could just easily make use of Data Annotations
public class Customer
{
public int Id { get; set; }
[StringLength(20)]
public string FirstName { get; set; }
public string LastName { get; set; }
}
and that's it. Another approach it could be the following:
public class Customer
{
public int Id { get; set; }
private string firstName;
public string FirstName
{
get { return firstName }
set
{
if(value!=null && value.length<20)
{
firstName = value;
}
else
{
throw new ArgumentException("The first name must have at maxium 20 characters", "value");
}
}
}
public string LastName { get; set; }
}
Consider both of the above approaches with having to revisit all your codebase and make this check. It's crystal clear that properties win.
Yes, it is possible through reflection. Nevertheless, I wouldn't worry about reflection -- people using reflection to defeat the design of your class is not something I worry about.
There is, however, something I do worry about: the phrase "Assuming that _property is only set by the setter of Property" is key. You are preventing users of your class from setting property to null.
You do not prevent, however, yourself or some other maintainer of your class from forgetting to only use the property INSIDE your class. In fact, your example has some one checking the field from inside the class rather than the property itself.... which means that, within your class, access comes from both the field and the property.
In most cases (where the problem could only come from inside the class) I would use an assertion and assert the field is not null.
If I really, really, really wanted to make sure that it wasn't null (barring reflection or people hell-bent on breaking things), you could try something like this:
internal class Program
{
static void Main()
{
string example = "Spencer the Cat";
UsesNeverNull neverNullUser = new UsesNeverNull(example);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = null;
Debug.Assert(neverNullUser.TheString != null);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = "Maximus the Bird";
Console.WriteLine(neverNullUser.TheString);
}
}
public class UsesNeverNull
{
public string TheString
{
get { return _stringValue.Value; }
set { _stringValue.Value = value; }
}
public UsesNeverNull(string s)
{
TheString = s;
}
private readonly NeverNull<string> _stringValue = new NeverNull<string>(string.Empty, str => str ?? string.Empty);
}
public class NeverNull<T> where T : class
{
public NeverNull(T initialValue, Func<T, T> nullProtector)
{
if (nullProtector == null)
{
var ex = new ArgumentNullException(nameof(nullProtector));
throw ex;
}
_value = nullProtector(initialValue);
_nullProtector = nullProtector;
}
public T Value
{
get { return _nullProtector(_value); }
set { _value = _nullProtector(value); }
}
private T _value;
private readonly Func<T, T> _nullProtector;
}
It is basically redundant. However, if it were mission critical or if for some reason it caused terrible side effects, it could remain. It is hard to tell, but part of your question was "can reflection change this value to null" to which the answer is yes and can be seen here in this linqpad demo
void Main()
{
var test = new Test();
test.Property = "5";
Console.WriteLine(test.Property);//5
FieldInfo fieldInfo = test.GetType().GetField("_property",BindingFlags.NonPublic | BindingFlags.Instance);
fieldInfo.SetValue(test, null);
Console.WriteLine(test.Property);//null
}
public class Test
{
private string _property = string.Empty;
public string Property
{
get { return _property; }
set { _property = value ?? string.Empty; }
}
}
I know this question is old, but look, I needed that one of my string properties never came up in null.
So I did this, and It worked for me
public string Operation { get; set; } = string.Empty;
In this way the default value is a string empty, but never null.

Signaling that the values of a variable have been rejected

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
}
);
}
}
}
}

Categories

Resources