Is it OK for a function that can throw an exception to have the [pure] attribute?
According to
https://msdn.microsoft.com/en-us/library/system.diagnostics.contracts.pureattribute(v=vs.110).aspx
PureAttribute attribute
Indicates that a type or method is pure, that is, it does not make any
visible state changes.
So it's quite possible to throw an exception from such a method e.g.
// factorial is a pure function: no state will be changed,
// just a computation
[Pure]
public static BigInteger Factorial(BigInteger value) {
// We can't return infinity with BigInteger and that's why have to throw the exception
if (value < 0)
throw new ArgumentOutOfRangeException("value", "value must be non-negative");
...
}
And what if I call this pure method as
BigInteger result = Factorial(1000000000);
one of the possible outcomes is OutOfMemory exception thrown
You can throw an exception, you are not making any visible state changes. Here example from Reference source.
[Pure]
private void VerifyWritable() {
if (isReadOnly) {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
}
Contract.EndContractBlock();
}
I agree with Dmitry.
According to documentation from msdn:
All methods that are called within a contract must be pure; that is, they must not update any preexisting state. A pure method is allowed to modify objects that have been created after entry into the pure method.
Throwing an exception is allowed and will not necessarily be considered as a changing the object state.
Related
Essentially I am creating a little IL injection DLL that uses MONO.CECIL and C#, primarily as a learning exercise for myself but also for my own future hobbyist use.
I am not particularly skilled with exceptions (or C#) and am unsure what the appropriate exception to throw is for when a runtime type mismatch occurs.
For example : I have a method that INJECTS a method call at a given point in a target DLL. The method takes as an arguement a Collection (parameters) to represent the variables to pass as parameters to the newly injected method call.
Before injecting I check for type parity between each member of the Collection (parameters) and the Collection from the method whose call I am injecting.
On a mismatch I want to throw an exception. But I could not really find any that fit. I would prefer to use existing exceptions where possible, rather than creating my own.
Here is the code :
private static bool ParameterParity(Collection<ParameterDefinition> p, Collection<VariableDefinition> v)
{
if (p.Count != v.Count)
{
return (false);
}
else
{
int index = 0;
foreach (ParameterDefinition parameter in p)
{
if (parameter.ParameterType.MetadataType != v[index].VariableType.MetadataType)
{
return (false);
}
index++;
}
}
return (true);
}
Here is the call where the exception will be thrown :
if (ParameterParity(source.Parameters, parameters) == false)
{
throw new NotImplementedException($"{Helper.AddParenthesis(nameof(PreInject), Helper.ParenthesisE.Square)}" +
$" : Parameter mismatch in TYPE or NUMBER" +
$". Functionality not supported.");
}
I temporarily have used the NOT IMPLEMENTED exception, but would prefer something more appropriate. A suggestion as to the appropriate Exception would be appreciated.
Thanks in advance.
Why are exceptions always accepted as a return type (thrown)?
Valid example 1:
public string foo()
{
return "Hello World!";
}
Invalid example (obviously):
public string foo()
{
return 8080;
}
Valid example 2:
public string foo()
{
throw new NotImplementedException("Hello Stackoveflow!");
}
I can see that my "Invalid Example" is 'throwing' and not 'returning' the Exception, however, my method does never return the type defined by the method. How come my compiler allows this to compile?
Exceptions are not return types, exceptions indicate an error in the method and that it cannot continue.
Your valid example 2 does not return anything, the compiler knows that it will always throw an exception, so it does not need to worry about returning.
If you had:
public string foo(int something)
{
if(something > 10){
throw new NotImplementedException("Hello Stackoveflow!");
}
}
it would complain, because you are not returning a value all the time.
Also, from your example, if you had: string val = something() in your code, val would never get set, because an exception is not a return value.
However, it is valid code, your function can either return a value based on its signature or throw an exception. If anything, you might expect a warning by the compiler. I'm not sure about C#, but in java if you have code that is determined to be unreachable you will get warnings, such as:
public string foo(int something)
{
throw new NotImplementedException("Hello Stackoveflow!");
return "OK";
}
This code would give you a warning, because it is impossible for this method to reach the return statement (but it is still valid code, at least if it were Java).
You can read about exceptions here: MSDN
Exceptions give you information about ocurred error. You can easly handle and throw them.
Say you were calling a method similar to the following, which you know is only ever going to throw one of 2 exceptions:
public static void ExceptionDemo(string input)
{
if (input == null)
throw new ArgumentNullException("input");
if (input.Contains(","))
throw new ArgumentException("input cannot contain the comma character");
// ...
// ... Some really impressive code here
// ...
}
A real life example of a method which does this is Membership.GetUser (String)
Which of the following would you use to call the method and handle the exceptions:
Method 1 (check the input param first first)
public static void Example1(string input)
{
// validate the input first and make sure that the exceptions could never occur
// no [try/catch] required
if (input != null && !input.Contains(","))
{
ExceptionDemo(input);
}
else
{
Console.WriteLine("input cannot be null or contain the comma character");
}
}
Method 2 (wrap the call in a try / catch)
public static void Example2(string input)
{
// try catch block with no validation of the input
try
{
ExceptionDemo(input);
}
catch (ArgumentNullException)
{
Console.WriteLine("input cannot be null");
}
catch (ArgumentException)
{
Console.WriteLine("input cannot contain the comma character");
}
}
I've had both methods taught over the years and wondered what the general best practise was for this scenario.
Update
Several posters were focusing on the method throwing the exceptions and not the way these exceptions were being handled, so I've provided an example of a .Net Framework method which behaves in the same way (Membership.GetUser (String))
So, to clarify my question, if you we're calling Membership.GetUser(input) how would you handle the possible exceptions, Method 1, 2 or something else?
Thanks
It depends, but generally, neither method presented is good. As has been said, in the first case, you are duplicating code. In the second, you are catching the exception without actually doing anything about it - not even rethrowing, just swallowing it. If you want just to log it or display some message, normally you should implement a global handler/logger using AppDomain.UnhandledException and do it there; this way, you don't have to pollute your code with unnecessary try/catch blocks.
The real question here is whether or not input being null or containing ',' is really an exceptional behavior in your specific case - e.g. if this is some GUI-entered string, then this should normally not result in an exception throw (end-user mistakes should be expected) and should be handled appropriately (e.g. with a warning to re-entry the input). In such case, using if statements to validate the input is the proper way. However, if input being null or containing ',' is an actual exceptional behavior (say, an API problem which indicates something's broken or missing) then throwing exception is ok. In this case, you can simply call ExceptionDemo(input) without try/catch. If you want to actually do something about the exception (e.g. change the input in some way), then use try/catch.
Callers should not assume anything about code they're calling.
Your first example is bad, because you're duplicating code: the caller performs almost (string.INOE() vs string == null) the same check as the callee (until either of them changes).
The second example is extremely bad as it ignores the thrown exceptions and gives its own interpretation to them.
As usual: it depends. If you have a properly layered application where the method calls are in your UI layer, you do want to just catch the exception the method throws: you'll want to display those errors to the user.
It depends on how many times ExceptionDemo is called and who it is exposed to. If it was used extensively, you wouldn't want to check the conditions before calling ExceptionDemo, when you know (and document) that ExceptionDemo does the checks anyway.
Given the return type is void, what about changing ExceptionDemo to have no effect if the input is wrong?
(Did you notice that you are stricter in Method 1 - the empty string is not a valid input, but in Method 2 it is)
I would recommend standard and generic structure as below :
public static void Operation(object input)
{
try
{
ValidateInput(input);
//Do Operation
}
catch (MySpecificException subSubExceptionType) //Catch most specific exceptions
{
//Log or process exception
throw;
}
catch (MySpecificException subExceptionType) //Catch specific exception
{
//Log or process exception
}
catch (Exception exceptionType) //Catch most generic exception
{
//Log or process exception
}
finally
{
//Release the resources
}
}
private static void ValidateInput(object input)
{
if(input == null)
throw new NoNullAllowedException();
//Check if properties of input are as expected. If not as expected then throw specific exception with specific message
}
Is it acceptable/desire If I throw an error from callee rather than from caller? Or should I get the error info from callee and then throw the exception from caller? Which one is preferred/desire way?
public static List<ProductBuilder> GetProductBuilders(GetProductsRequest productsRequest)
{
List<ProductBuilder> productBuilders = new List<ProductBuilder>();
...
... // Some logics to populate productBuilders
if (productBuilders.Count == 0)
{
Logger.LogMessage(productsRequest.SessionId, "No ProductBuilders were created.");
throw new ProductException(ProductException.ExceptionCode.SaveFailed, "No Service has qualified.");
}
return productBuilders;
}
Your answer is stick to the Single responsibility principle.
In the example you provided the method GetProductBuilders has (at least) two responsibilities:
Populate the collection of objects
Validate the result count
If you refactor your code to:
public static List<ProductBuilder> PopulateProductBuilders(...)
{
// Logic to populate the collection
}
public static List<ProductBuilder> GetProductBuilders(GetProductsRequest productsRequest)
{
var productBuilders = PopulateProductBuilders();
if(!productBuilders.Any())
{
Logger.LogMessage(productsRequest.SessionId, "No ProductBuilders were created.");
throw new ProductException(ProductException.ExceptionCode.SaveFailed, "No Service has qualified.");
}
}
then it becomes clear which method should perform the validation on empty list and throw the exception.
In other words, if you separate the responsibilities of your methods you'll have a better picture of where to throw exceptions.
IMHO,
Your framework class code should throw exception if any your class is expecting some parameters from the client , otherwise client should handle the output returned.
So, I have a list containing a custom class, MyClass
MyClass has properties, which can be null (but aren't meant to be).
When this class is sorted, using a custom sorter, where the sorter accesses this null property and throws an exception, the exception is considered unhandled, even though there is a try-catch block around the sort method.
Now for some reason the exception still gets written to the console, which is what the exception handler is doing.
I have a real application with this same issue, causing my unit tests to fail, even though the exception is handled correctly and I cannot explain this.
So I have attached some sample code to explain myself better, run this from VS.
Updated Code
Results:
System.InvalidOperationException
Failed to compare two elements in the array.
Done!
So it seems to be handling my custom exception, and throwing its own?
using System;
using System.Collections.Generic;
using System.Data;
namespace TestSortException
{
class Program
{
static void Main()
{
try
{
var list = new List<MyClass>
{
new MyClass("1"),
new MyClass(null),
new MyClass("fdsfsdf")
};
list.Sort(new MyClassSorter());
}
catch(Exception e)
{
Console.WriteLine(e.GetType());
Console.WriteLine(e.Message);
}
Console.WriteLine("Done!");
Console.ReadLine();
}
}
class MyClassSorter : IComparer<MyClass>
{
public int Compare(MyClass x, MyClass y)
{
// try
// {
if (x.MyString == y.MyString)
return 0;
// Unhandled??? Exception here
if (x.MyString.Length > y.MyString.Length)
return 1;
return -1;
// }
// catch (Exception)
// {
// return -1;
// }
}
}
class MyClass
{
private string _myString;
public string MyString
{
get
{
if (_myString == null) throw new DataException("MyString is Null");
return _myString;
}
}
public MyClass(string myString)
{
_myString = myString;
}
}
}
There's a try/catch block round the Sort method, yes - and that catch block catches the exception. In other words, Sort throws an exception and your catch block catches it. It doesn't propagate out beyond Main - so "Done!" is printed.
This is exactly what I'd expect. In what way is it "unhandled" in your experience? Were you expecting Sort not to throw the exception? It needs to do something to indicate the failure to compare two elements, and this seems to be the most appropriate course of action.
In what way are your unit tests failing? Are you deliberately giving them invalid data? How do you want your comparison code to react to invalid data? If it should ignore it (and return a comparison based on another property), then you should actively check the property rather than letting an exception propagate. In most cases I'd rather allow the exception if this indicates that there's a bug earlier on though.
EDIT: Based on your other comments, it sounds like you're doing the appropriate thing, letting the exception bubble up - but it's not clear in what way you're seeing the exception not be handled.
If you're running in the debugger, it may be breaking on the exception being thrown, but that doesn't mean it won't be handled. Try either changing your exception settings or running without the debugger.
EDIT: Yes, Sort will catch the exception and throw an InvalidOperationException instead - but you can use the InnerException property of that exception to get hold of the original one. It's unfortunate that the documentation doesn't specify this :(
For example, when it checks that string "1" isn't equal to null. But it wants then to compare lengths of "1" string and null => which is impossible.
I assume you work with .Net Framework 4.0. The new thing there is that a NullRefenrenceException can not be caught any more (similar to OutOfMemory exception).