Exception Handling - is this good practice? - c#

I am wondering if what i am going to do is good or bad thing. I have that class:
public class Element : IElement
{
public float? Max { get; private set; }
public float? Min { get; private set; }
public float? Average { get; private set; }
public bool HasValue { get; private set; }
public void SetRange(float? min, float? max)
{
if (min >= max)
{
throw new WrongElementValueException("Min must be greater than max!");
}
else if (min < 0f || max < 0f)
{
throw new WrongElementValueException("Min/max must be greater than 0!");
}
else if (min > 100f || max > 100f)
{
throw new WrongElementValueException("Min/max must be lesser than 0!");
}
else
{
Min = min;
Max = max;
Average = (min + max)/2f;
HasValue = true;
}
}
}
The user will set the values using SetRange() method. But he has some constraints like Min must be bigger than Max, and neither of them should be bigger than 100 or lesser than 0.
Should I use those exceptions in this place? Or is there any better method to handle wrong user input?
I hope my question isn't to general.

This is an appropriate practice, yes.
Though I imagine consuming code would be expecting an ArgumentException rather than this exception type, but that may be a relatively minor point.
When the input is invalid, and the object has no way of meaningfully continuing otherwise, then throwing an exception is an appropriate and expected response. It's up to consuming code to use the object properly, handle errors, report back to the user, etc.
The alternative is for this object to "try to figure out what to do" which often leads to some pretty bad coding practices. For example...
Suppose you instead want to return an error message instead of throwing an exception. What if consuming code doesn't check for that error message? The object would be left in an unknown and invalid state and could quietly introduce bugs. Whereas if consuming code didn't check for the exception then the program would clearly and obviously fail and would need to be appropriately corrected. Clear and obvious failures are a lot easier to support than subtle and unnoticed ones.
Suppose you want to "show a message to the user" instead. That would requiring tightly coupling this object to a presentation layer, which defeats object oriented principles and makes the code very rigid and difficult to maintain.
This object does one thing, and only that one thing. If it's invoked in such a way that it can't do that one thing, an exception is an expected and appropriate failure condition.

else if (min < 0f || max < 0f)
throw new WrongElementValueException("Min/max must be greater than 0!");
else if (min > 100f || max > 100f)
throw new WrongElementValueException("Min/max must be lesser than 0!");
I'd note that there is already ArgumentOutOfRangeException that's defined for precisely this sort of case.
if (min >= max)
throw new WrongElementValueException("Min must be greater than max!");
This should definitely be an ArgumentException, but if WrongElementValueException inherits from ArgumentException, then that's fine.
Your general approach is sound. I'd consider going further:
HasValue = true;
Why allow for the class to ever not have a value. Consider if you add:
public Element(float min, float max)
{
SetRange(min, max);
}
Now you can never have an instance without its values set, and can get rid of HasValue entirely.
Note though that I changed this from float? to float. You might well be advised to do that throughout the class. Otherwise if you have a need for cases where Min and Max are null, (and therefore don't want to get rid of HasValue) you need to catch that case in SetRange:
public void SetRange(float? min, float? max)
{
if (min < 0f || max < 0f || min > 100f || max > 100f)
throw new ArgumentOutOfRangeException();
if (min >= max)
throw new WrongElementValueException("Min must be greater than max!");
Min = min;
Max = max;
if(min.HasValue && max.HasValue)
{
Average = (min + max)/2f;
HasValue = true;
}
else
{
Average = null;
HasValue = false;
}
}
(I'd also generally favour double and double? over float and float? unless you've a strong reason otherwise).
Incidentally, we generally use "exception handling" to talk about how code that's using this code deals with the fact that your code threw an exception, with just what the best thing to do is depending on the context of that code rather than this code.

An excption is usefull whenever a valid program-flow is not possible (e.g. connection to database lost). Proofing user-input and throwing exception if values are not valid is absolutely ok thus, whereas you may also use the allready suggested ArgumentException.

It's good practice to handle exception in program if you are throwing and catching it correctly. But here it's trivial matter ,no need to throw and object where as you can restrict it by simple console print.
Both will work same in this scenario.
Throwing an exception would much useful when there are many inner function calls and you don't know which one will cause exception at that time.
and By the way don't you think these is wrong one.
if (min >= max)
throw new WrongElementValueException("Min must be greater than max!");// your are printing min should be greater than max and you are checking the same.

Related

Error Loging with variable names and values that was used in method

Is there any way, to log all variables and the values that were used in the method?
I want to see log information like I showed in the method ErrorWriter. I don't want to use something like ErrorWriter(names, values). Can anyone suggest a solution?
static int number3;
static void Main(string[] args)
{
number3 = 0;
Method(1, 2);
}
static void Method(int number, int number2)
{
int number4;
try
{
number4 = number / number2 / number3;
}
catch
{
ErrorWriter();
}
}
private static void ErroWriter()
{
/// number = 1
/// number2 = 2
/// number3 = 0
}
I need information about variable values which was used. For example. If i have a line number4=number/number2/number3 . How can i know which variable value was 0? Number 2 or number 3? That's why i need exact values. I don't want to hardcode parameter for every different method. I need dynamic solution.
I would use some kind of aspect programming/interception for this. Any other approach you take will probably end up being to low level or complicated for something that shouldn't be on the actual class you are implementing.
Error Handling is not necessarily one of the responsabilities of your class so it can be delegated to an aspect.
One possible solution would be to use some kind of IoC framework (like Unity and Ninject, there are many others) and set up your classes to be intercepted by an error handling interceptor, which will catch exceptions and log the parameters in those cases.
This article has an example using Unity that can point you to the right solution
As others have stated, using standard error handling routines would probably serve you much better than what you're trying to accomplish here.
Anyway, your ErrorWriter method could take a parameter of type int[].
chatch
{
ErrorWriter(new int[3] { number1, number2, number3 });
}
(...)
private static void ErrorWriter(int[] numbers)
{
int index = 1;
foreach(var i in numbers)
{
Console.WriteLine("number" + index.ToString() + " = " + i.ToString());
}
}
Seems like you would want to avoid the try/catch in this case.
Check in Method if your input is valid (ie. number, number 2 and number 3). Throw exception if validation fails.
If all you want is to be able to determine if one of the variables is zero (or has failed validation), throw the Exception in a check like follows:
private void Method(int number, int number2) {
if (number3 == 0) throw new Exception("number3 is zero, resulting in division by zero");
if (number2 + number == 0) throw new Exception("number2 + number is zero");
number 4 = (number2 + number) / number3
}
No try/catch needed. The exception will bubble up.
Always check your input (instance variables and parameters) before using in any method!

Check if calculation exceeds MaxValue

I currently got the following method, which is returning me percent-values. For example for an item-price of $350,000 and a percentage of 7%, it returns 24,500.
public static decimal GetPercentValue(decimal? percentage, decimal baseValue)
{
decimal result = 0m;
if (percentage != null)
{
try
{
result = Convert.ToDecimal(baseValue * percentage / 100m);
}
catch (OverflowException)
{
result = 0;
Logger.Warn("OverflowException caught in GetPercentValue() - should better be handled UI-Sided!");
}
}
return result;
}
I don't think this is handled the right way, so is there any way to avoid an exception in this situation?
An OverflowException is being thrown when a user enters an insane number like 999,999,999,999,999,999 and calculates 9999999999% of it. This way I can't check percentage or baseValue for <= decimal.MaxValue simply because they aren't... The calculation result itself then exceeds the decimal range.
This is an old question, but I ran into a similar issue, and thought to provide a possible alternate solution. The problem happens when some calculation of two numbers produces a number greater than a MaxValue. This causes an exception, and is hard to test in the usual way:
decimal existingValue = decimal.MaxValue;
decimal newValue = (decimal)100;
//doesn't work -- exception thrown here
if(existingValue + newValue <= decimal.MaxValue)
{
}
The solution that seems to work for me (without using a Try-Catch block) is to rewrite the equation, in this case as a subtraction:
if(decimal.MaxValue - existingValue >= newValue)
{
//DoSomething
}
MaxValue isn't exceeded because of the subtraction. I haven't tried a multiplication/division example, but I'm guessing it would work too.
The error handling should (most likely) be done outside the method. Right now you're hiding exceptions and returning wrong results (0 is returned when an error occures). The caller of your method cannot tell if the result is correct or if it's due to an OverflowException.
I'd rewrite the method like that:
public static decimal GetPercentValue(decimal? percentage, decimal baseValue)
{
if (percentage == null)
return 0;
return baseValue*(percentage.Value/100);
}
And optionally add a validation method that the user can call to check the parameters before calling the real method.. validation errors could be displayed in the UI:
public static string ValidatePercentValue(decimal? percentage, decimal baseValue)
{
try
{
GetPercentValue(percentage, baseValue);
return null;
}
catch (Exception ex)
{
return ex.Message;
}
}
Besides that note that...
baseValue*(percentage.Value/100)
... is better than...
baseValue*percentage.Value/100
Try to calculate 100% of decimal.MaxValue. The first one works while the second one throws an OverflowException.

What is the correct way to limit the range of values a property will accept?

I have a user control with some public properties. A particular property is an integer, but must only accept positive values that are less than a const max value. At present I do the following:
private int markerwidth = 2;
[DefaultValue(2), Category("Appearance"), Description("Size of position marker")]
public int MarkerWidth
{
get
{
return this.markerwidth;
}
set
{
if (value > 0 && value <= MAXMARKERWIDTH)
{
this.markerwidth = value;
}
}
}
This does the job, but fails silently. I guess I could add logic to use 0 for negative values and the max value for those that exceed it, but it's still not ideal.
By way of contrast, the TabValue property (inherited from UserControl) complains if I try to set a negative value at design time (and presumably at run time).
If this achieved with a normal exception? Or is there a better way? An attribute maybe?
The most optimal way is to achieve via exception. Just continue your code
if (value > 0 && value <= MAXMARKERWIDTH)
{
this.markerwidth = value;
}
else
{
throw new ArgumentOutOfRangeException("Invalid value. Value must be between 0 and " + MAXMARKERWIDTH.ToString());
}
EDIT
Yes, Wiktor Zychla is absolutely right! I corrected the answer.
There is a builtin ArgumentOutOfRangeException, I guess it fits here.

C# value overflow limiting

I need to limit the value on overflow.
I implemented this as follows:
public static sbyte LimitValueToSByte(this int val)
{
if (val > sbyte.MaxValue) return sbyte.MaxValue;
if (val < sbyte.MinValue) return sbyte.MinValue;
return (sbyte)val;
}
Is there a more elegant way?
This is the code in a time critical system, therefore performance is important.
That seems like a perfectly readable and valid code that doesn't need any improvement whatsoever. It's just the name of the method. Maybe use ToSbyte rather than LimitValueToSByte.
Can't think of a better way to write that function.
I'd call it ClampToSByte, since this kind of limiting operation is usually called Clamp. Limit is a bit less specific, and allows for other boundary conditions, such as wrapping around.
You should be careful if you implement similar code for floating point numbers. In particular you need to decide what behavior you want for NaNs and signed zeros. But luckily that are no issues with integral values.
Looks pretty good to me. If you want something more elegant, how about a generic clamp function?
public static T Clamp<T>(this T value, T min, T max)
where T : IComparable<T>
{
if (value.CompareTo(min) <= 0) return min;
if (value.CompareTo(max) >= 0) return max;
return value;
}
(Warning: I didn't test this.) You could use it like this:
int a = 42;
sbyte b = (sbyte)a.Clamp(sbyte.MinValue, sbyte.MaxValue);
My new solution of this problem:
public static sbyte Clamp(this int val)
{
return (sbyte)Math.Max(Math.Min(value, sbyte.MaxValue), sbyte.MinValue);
}

Implementing parallel exceptions to get trees of errors?

Consider the following code:
// this method should add numbers, the requirements are:
// x >= 3 and y <= 5
int add(int x, int y)
{
if(x < 3) throw new ...;
if(y > 5) throw new ...;
}
It's absolutely traditional approach, but in case you pass invalid values for both x and y, you'll only get an exception for x. Why x and not y? Just because you first check x and only then y. Why? That's basically the main question.
In the code above, there's absolutely no sense in checking x before y or y before x. Just because the idea of execution flow in a single thread, some statements are executed before others.
I'm thinking about implementing a mechanism for working with parallel exceptions. The idea is, if there are 2 statements that can be executed simultaneously (execution order doesn't matter) and both of them throw exceptions, I'd like to be able to handle all these exception. The pseudo-code is like following:
// this method should add numbers, the requirements are:
// x >= 3 and y <= 5
int add(int x, int y)
{
parallel
{
if(x < 3) throw new ...;
if(y > 5) throw new ...;
} // point A
return x + y;
}
Somewhere at point A the cumulative exception is thrown. Have you ever seen this approach before, or may be even implemented something of that kind? The main goal here is that if you have a complicated operation, that uses a number of another operation, and the "topmost" operation fails for some reason, you're able to get full diagnostics for what was wrong: not a single error (or a number of nested errors), but a tree of errors.
The questions are:
What do you think?
Have you seen it before?
Have you tried implementing something similar?
Perhaps use an AggregateException?
You seem to want to enforce a set of business rules.
One approach is to create a collection of broken rules and add specific broken rules (e.g. input too short, input must be alphanumeric) as separate elements of that collection, then throw a BrokenRulesException that includes the collection of broken rules as a parameter.
That allows the caller to fully understand what's wrong with the input without changing any language semantics.
Whats wrong with:
int add(int x, int y)
{
if(x < 3 || y > 5)
throw new Error("Incorrect Parameter, x must be >= 3 and y must be <= 5");
}
I think that this would be extraordinarily difficult without implementing something called a continuation -- the ability to return the current state of a function for delayed execution.
Basically, the problem is that instead of an exception (or, rather, a thrown... thing as you do not always have to throw an Exception object in all languages) being a message that a point which cannot be handled has been reached, it would have to return both that and the ability to force continuation past that point anyway. (Thus, you would need continuations)
Additionally, at least on the lower level, this would force the language to always throw an object in those cases. Throwing an int, on the other hand, is occasionally useful.
All of that said, there is nothing stopping you from, say, implementing a macro which works similar to how you've described.
// this method should add numbers, the requirements are:
// x >= 3 and y <= 5
int add(int x, int y)
{
if(x < 3 && y > 5) throw new ...;
if(x < 3) throw new ...;
if(y > 5) throw new ...;
}
Can't this be fairly easily done, without the need for AggregateExceptions or similar:
string ErrorMessage="";
if(x<3) ErrorMessage += "x must be >=3\n";
if(y>5) ErrorMessage += "y must be <=5\n";
if(ErrorMessage!="") throw new Exception(ErrorMessage);
if a string is too simple, it's easy to do something similar with a more complex object type.

Categories