Safe usage of .FirstorDefault()? - c#

When using Enumerable.FirstorDefault(), do I need to always catch the ArumentNullException that can be thrown when the collection operated on is null?
In the past I've always just done something like this:
WorkflowColorItemType associatedColor = ColorItems
.Where(ci => ci.AssociatedState == WorkflowStateStatus.NotStarted)
.FirstOrDefault();
if (associatedColor != null)
{
this.ColorItems.CurrentColor = associatedColor;
}
In the context of this code snippet, I would never expect ColorItems to be null but is it good practice to be enclosing every instance of snippets like this in try catch blocks so I can handle the off chance that the ColorItems collection might be null?

If you don't expect the collection to ever be empty, and it would be an error in your program for it to be empty, then don't use FirstOrDefault in the first place, use First. Since it's not an expected situation for you to be in you want to draw attention to the problem because it's a sign that something is wrong.
If it's entirely valid for the collection to be empty, and you want to use the first item only if there is at least one item, then using FirstOrDefault and providing a null check is fine.
Apply the same logic to the collection being null, and not empty. If it is expected that the collection be allowed to be null, then check for it using an if. If it's not expected that the collection be allowed to be null (which is generally the case for most uses of collections) then you shouldn't check, and you want the exception to be thrown as it will draw attention to the bug in the code that is supposed to populate that collection. Trying to catch the exception and move on is trying to obscure the bug which prevents you from finding and fixing it.

Yes, certainly. You need to be defensive all the time.
In fact, if associatedColor is null, that means there is something wrong, hence you need to handle it.
In fact, your code used to be wrapped in a try/catch block to handle exceptions, since, exceptions are "expensive", this is cheaper and nicer way to handle exceptional cases.
In any case, I would almost always use FirstOrDefault or something simirlar, like SingleOrDefault then I would do the null check.

The built in LINQ functions (like .Where() here) always return an empty enumerable if there are no results, not null. So there is no need to check for null after doing the .Where()
Depending on where ColorItems comes from, you should check for null on the object:
if (ColorItems != null)
{
}
else
{
}
There's no need to put a try/catch block around the code, but you should be checking for null just to be safe. In fact, using try/catch in a scenario like this, where you can just check for a null object, is a bad programming practice.

Related

Is there any point calling Any() before a for each?

I've been looking at some code I've refactored which makes use of the null object pattern so will always return an empty list if null.
However some of the other code within the function makes use of an Any() check for doing a ForEach().
Is there any benefit to doing so?
e.g.
var items = new List<items>
items.AddRange(GetItems(1))
if (items.Any())
{
items.ForEach(item => { // Do something with item });
}
I realise as long as there is no need for the null guard this is safe, but I wondered whether there are any best practices with LINQ and C# relating to this.
Cheers,
Jamie
The only check you could do is check if items is null, as you already said. But if you handle that case you should keep in mind to consider the else condition as well and how your application should react in that scenario.
Other than that, there is no need to check if there are items in the list if you just want to iterate over them.
Sorry I am unable to say any best practices for Linq/C#, but I will share my thoughts on the usage of Any before ForEach
However some of the other code within the function makes use of an
Any() check for doing a ForEach().
Having this Any() before ForEach() will passively suppressing null reference exception and carrying on with our operation. This appears to be good but actually the code permits others to send null values.
I normally use Debug.Assert(!=null) for the places where its possible to inject null values. This way these kind of errors can be captured in unit tests and ensure those who calls this code will be notified and wont allow to break this code. Because if null is tolerated, we will not address the root cause - which is we need to initialize objects in proper places.

Is it possible to continue running code from the point of failure?

Okay, I have some very simple code which I will post below. Essentially, I have a connection to a database and I want to map a subset of columns in a query to a particular class. The problem is that it is possible for these to be null.
I would like to know if it is possible if an exception is thrown at a particular line, can we resume the entire block from the next line.
So if this code below was to execute and Line 6 catches an error. Is there an elegant way to catch the exception and make the code resume running at line 7. Essentially making it as though line 6 was never executed.
private static Column MapTableToColumn(OracleDataReader reader){
Column c = new Column();
c.ColumnName = Convert.ToString(reader["COLUMN_NAME"]);
c.DataType = Convert.ToString(reader["DATA_TYPE"]);
c.DataLength = Convert.ToInt32(reader["DATA_LENGTH"]);
c.DataPrecision = Convert.ToInt32(reader["Data_Precision"]);//<---Line 6
c.DataScale = Convert.ToInt32(reader["Data_scale"]);//<--- Line 7
c.AllowDBNull = Convert.ToBoolean(reader["ALLOW_DB_NULL"]);
c.IsReadOnly = Convert.ToBoolean(reader["IS_READ_ONLY"]);
c.IsLong = Convert.ToBoolean(reader["IS_LONG"]);
c.IsKey = Convert.ToBoolean(reader["IS_KEY"]);
c.KeyType = Convert.ToString(reader["KEY_TYPE"]);
c.IsUnique = Convert.ToBoolean(reader["IS_UNIQUE"]);
c.Description = Convert.ToString(reader["DESCRIPTION"]);
return c;
}
It is important to note I am not asking for best practice, it is not something I intend to use in actual code (unless its absolutely genius). I simply want to know if this is possible and how one would go about doing this if it were.
My Research
Most of my research is proactive as opposed to reactive. I would attempt to know if it is possible for the given field to be null before it is read from. If it is, then I'd do a check to determine if the field is null and then set it to a default value. It essentially avoids the possibility of an error happening which I believe is a very good solution. I just wanted to attempt this as I know that when an exception is thrown, the most inner exception contains the line number at which it was thrown. Based on this if you put the exception inside of the class throwing the exception you should hypothetically be able to use reflection in order to continue running from its last point. I'm just not sure how you'd go about doing this. I've also considered the possibly of putting try catches around every single line which I think would be very effective; however, I think that it would be very ugly.
No, what you are asking for is not possible in C#.
Instead the proper solution to this problem is to use better parsing methods that won't throw exceptions in the first place. If your input values can be null, then use parsing methods that can accept null values.
The first thing you probably need to do is use nullable types for your int/bool fields, so that you can support null values. Next, you'll need to create your own methods for parsing your ints/bools. If your input is null, return null, if not, use int.TryParse, bool.TryParse (or as for each if your input is the proper type, just cast to object).
Then by using those methods, instead of Convert, you won't be throwing exceptions in the first place (which you shouldn't be doing here even if it could work, because exceptions are for exceptional cases, not expected control flow).
If the exception is expected then it is not exceptional. Never never never catch a null reference exception. A null reference exception is a bug. Instead, write code to avoid the bug.
You can easily write helper methods that test for null, or use methods like Int32.TryParse that can handle malformed strings.
Check for IsDBNull
SqlDataReader.IsDBNull Method
And Reader has methods for each SQL datatype
For example
SqlDataReader.GetSqlBoolean
If the data is in SQL as string (char,nchar) then first check for null and then TryParse
For example
DateTime.TryParse
And ordinal position is faster
This is a sample for a nullable Int16
Int16? ID;
ID = rdr.IsDBNull(4) ? (Int16?)null : rdr.GetInt16(4);
If you want a default
Int16 ID;
ID = rdr.IsDBNull(4) ? 0 : rdr.GetInt16(4);
You'd need a try/catch around every single variable assignment, and you'd need to initialize all your Column instance values before you tried. This would be relatively slow.
As for reflection based on the line number: I wouldn't rely on the line number because one simple, innocent change to the code will throw it off completely.
I'd check for nulls specifically. If you expect them you can't hardly call them "exceptions". The method that does that is reader.IsDBNull. It takes the column index (not the column name) so you'll need to resolve the index using reader.GetOrdinal:
if (reader.IsDBNull(reader.GetOrdinal("Data_Precision"))) {
// It's null
} else {
// It's not null
}

Try Catch or If statement?

if you think there is a possibility of getting a null pointer exception, should you use an if statement to make sure the variable is not null, or should you just catch the exception?
I don't see any difference as you can put your logic to deal with the null pointer in the if statement, or in the catch block, so which one is best practise?
I would say ALWAYS use logic to catch the exception, not try/catch.
Try/Catch should be used when you validate but some strange thing happens and something causes an error so you can handle it more gracefully.
There is no single answer that will suffice here, it depends.
Let's take a few scenarios so you can see what I mean.
Scenario: Method that takes a reference type parameter that does not accept null
You're defining a method, it takes a reference type parameter, say a stream object, and you don't want to accept null as a legal input parameter.
In this case, I would say that the contract is that null is not a valid input. If some code does in fact call that method with a null reference, the contract is broken.
This is an exception, more specifically, it's an ArgumentNullException.
Example:
public void Write(Stream stream)
{
if (stream == null)
throw new ArgumentNullException("stream");
...
I would definitely not just let the code execute until it tries to dereference the stream in this case, instead crashing with a NullReferenceException, because at that point I lost all ability to react when I know the cause.
Q. Why can't I return false instead of throwing an exception?
A. Because a return value is easy to silently ignore, do you really want your "Write" methods to just silently skip writing because you made a snafu in the calling code, passing the wrong stream object or something that cannot be written to? I wouldn't!
Scenario: Method returns a reference to an object, sometimes there is no object
In this case the contract is that null is a legal result. In my opinion, null is something to avoid because it is quite hard to make sure you handle correctly everywhere, but sometimes it is the best way.
In this case I would make sure to if my way around the result, to ensure I don't crash when the null reference comes back.
Generalisation
If you take a close look at the above two scenarios, you'll note one thing:
In both cases it comes down to what is being expected, what the contract is.
If the contract says "not null", throw an exception. Don't fall back to the old-style API way of returning false because an exceptional problem should not be silently ignored, and littering the code with if statements to ensure every method call succeeds does not make for readable code.
If the contract says "null is entirely possible", handle it with if statements.
Advertising
For getting a better grip on null problems, I would also urge you to get ReSharper for you and your team, but please note that this answer can be applied to any type of exception and error handling, the same principles applies.
With it comes attributes you can embed into your project(s) to flag these cases, and then ReSharper will highlight the code in question.
public void Write([NotNull] Stream stream)
[CanBeNull]
public SomeObject GetSomeObject()
To read more about the contract attributes that ReSharper uses, see
ReSharper NullReferenceException Analysis and Its Contracts
Contract Annotations in ReSharper 7
Well. Exceptions are just that. Exceptions. They are thrown when something unforseen has happened and should not be part of the normal program flow.
And that's what is happening here. You expected the argument to be specified when it's not. That is unexpected and you should therefore throw your own exception informing the user of that. If you want to get bonus points you can also include the reason to WHY the argument must be specified (if it's not obvious).
I've written a series of posts about exceptions: http://blog.gauffin.org/2013/04/what-is-exceptions/
From a performance standpoint it really depends what you're doing. The performance impact from a try/catch block when no exception is thrown is minimal (and if you really need that last few percent of performance, you probably should rewrite that part of your code in C++ anyway). Throwing exceptions does have a major impact on simpler operations such as string manipulation; but once you get file/database operations in the loop they're so much slower that again it becomes a trivial penalty. Throwing across an App Domain will have a non-trivial impact on just about anything though.
Performance in Operations/second:
Mode/operation Empty String File Database Complex
No exception 17,748,206 267,300 2,461 877 239
Catch without exception 15,415,757 261,456 2,476 871 236
Throw 103,456 68,952 2,236 864 236
Rethrow original 53,481 41,889 2,324 852 230
Throw across AppDomain 3,073 2,942 930 574 160
Additional test results along with the source for the tests is available from the article Performance implications of Exceptions in .NET
I would rather suggest you use if-statement for NullReference exception. For other exception, try-catch should be good enough.
The reason I suggest if-statement for NullReference exception is because C# will not tell which variable is null. if that line has more than one object could be null, you will loss track. If you are using if-statement, you can have better logging to help you get the enough information.
The main Question is if it is a good idea to have methods returning Null at all, personally i do not have any problem with this, but as soon as you try to access modifiers of an object returned from this method and you forget to check if it is assigned this becomes an issue.
Ken has a good answer about this:
If you are always expecting to find a value then throw the exception
if it is missing. The exception would mean that there was a problem.
If the value can be missing or present and both are valid for the
application logic then return a null.
See this disscussion abou tthis issue:
Returning null is usually the best idea if you intend to indicate that
no data is available.
An empty object implies data has been returned, whereas returning null
clearly indicates that nothing has been returned.
Additionally, returning a null will result in a null exception if you
attempt to access members in the object, which can be useful for
highlighting buggy code - attempting to access a member of nothing
makes no sense. Accessing members of an empty object will not fail
meaning bugs can go undiscovered.
Some further reading:
No Null Beyond Method Scope
Should We Return Null From Our Methods?
using try catch for the statements is not an good idea. because when you use try catch them it seems that if some error comes the code will not turninate the application. but if you are sure about what kind of error can come you can tap the error at that point. that will not produce any unknown errors. for example.
string name = null;
here i am going to use the name variable and i am sure that this will throw Null Refrance Error .
try
{
Console.writeLine("Name ={0}",name);
}
catch (NullRefranceException nex)
{
//handle the error
}
catch(Exception ex)
{
// handle error to prevent application being crashed.
}
This is not a good practice while you can handle this kind of error and make your code more readable. like.
if(name !=null)
Console.writeLine("Name ={0}",name);
In my experience using if is better but only if you actually expect a null reference pointer. Without any bit of code or context its difficult to say when one option is better than the other.
There's also a matter of optimization - code in try-catch blocks won't be optimized.
In general, try-catch blocks are great because they will break (move to the catch statement) whenever the exception occurs. If-else blocks rely on you predicting when the error will happen.
Also, catch blocks won't stop your code from halting when an error is hit.
Its always better to use Try Catch other than if else
Here Exceptions are two types namely handled and UN-handled exceptions
Even if u want to handle some function when the Exception u can handle it...
Handled exception always allows you to write some implementations inside the Catch block
Eg. An Alert Message, A new Function to handle when such exception occurs.

When to raise an exception or return null?

I have a few functions on Data access layer
public Order RetrieveById(int id)
public List<Order> RetrieveByStatus(OrderStatus status)
Now i am bit confuse on exception raising.
In case of RetrieveById function, id which is less than 1 is an invalid id therefore i feel like raising an exception. And i feel like returning null for the Id which doesn't exist in the database. Then it feels like i am over complicating.
In case of RetrieveByStatus, i feel like returning a empty list when there is no data in the database for that status.
However i have seen that some people raising an exception when RetrieveById cannot return anything but then RetrieveByStatus should not raise exception when there is no record or should it?
Could anyone please clarify these concepts for me?
In the first case i would possibly go for a exception and handle myself,instead of returning null.What if your first method is used in a way that the returned object is saved to a Order reference.There is a very high chance of NullReferenceException being thrown,when someone tries to call a method or property on that object.
For the second method i would go for a empty list as some have suggested.
I would prefer to return null in the first case and an empty list
in the second case.
But if you want to raise exception then You can raise exception for public Order RetrieveById(int id) because it means that id is not valid as calling the first method means that you know the id and the it needs to be there.
In the second case the OrderStatus might be valid and there is not record found against it so returning an empty list is a good idea.
Read MSDN first: Creating and Throwing Exceptions (C# Programming Guide). It lists both situations when you are expected to throw an exception, and when to avoid it.
Also take into account What is the real overhead of try/catch in C#?
In any case you'll have to process either null return or an exception thrown
As for myself, I'd prefer in both your methods not to throw exception explicitly. I'd say, there is nothing bad, if your method returns null, if it failed to find an object by id. Whereas the RetrieveByStatus method could return an empty collection, not null.
Besides you could follow the pattern used in LINQ, where you have, say, Enumerable.First and Enumerable.FirstOrDefault methods (either throwing an exception or returning null), so you could use the appropriate one in a certain situation, when the id is 100% valid or when on the contrary it could be missing. While methods returning a sequence of elements don't throw exceptions if the sequence to return appears to be empty; consider Enumerable.Where.
I like to avoid returning null whenever possible, because NullRefExceptions are much more cryptic than a specific exception, say OrderNotFoundException. Also, code gets pretty obtuse when you have to constantly expect entities to be null. This ought to be an exception case anyway -- where did you get that id if it doesn't exist in the db?
On the cases you suspect this is more likely to throw an error, you could add a DoesObjectExist or TryGet type method (or even extension method).

Whether to check for null

I know that you should always check incoming params to a method for null. But what if I have this scenario with a try/catch referring to a local variable. Do I really need to check for null below? Because it's gonna catch it anyway if it's null and the next line of code tries to use the refundResponse variable:
public string DoRefund(...)
{
try
{
......
string refundTransactionID = string.Empty;
......
RefundTransactionResponseType refundResponse = transaction.DoRefund(...);
if (refundResponse != null)
refundTransactionID = refundResponse.RefundTransactionID;
.....
}
catch (Exception ex)
{
LogError(ex);
return ex.ToString();
}
}
Remember I'm talking specifically about local variables and checking those inside a method, not incoming params to a method.
All I'm asking here is do I need to check for null before setting refundTransactionID or do I just set it without the if assuming that the compiler will handle and throw if it is null which will be caught and thrown back as a string to the caller in this case.
or should it be
if (refundResponse == null)
return null;
or just take the check out completely for this local variable assignment and then since in this case I have a try/catch I'm handling any exceptions picked up by the compiler naturally by returning the exception as a string to the caller (it was not my decision to send back a string, it was a requirement by my boss...so bypass that debate for now):
refundTransactionID = refundResponse.RefundTransactionID;
ultimately the rest of the code further down the line in the method is dependent on a valid refundTransactionID.
Exceptions are for exceptional conditions. If you can check for a continuable error, do so, please!
I know that you should always check
incoming params to a method for null.
No, not necessarily. What you should specify is the contract of your method. It's perfectly acceptable (and common) to specify that you'll throw a NullPointer/NullReferenceException for a null parameter. Then you don't need any checking.
You can also check for null, but this only makes sense if you can actually handle a null usefully (e.g. substitute a default value).
You should have to check for null in that instance. Your application logic should be able to handle these kind of situations, without the need for exceptions.
An alternative to testing is the Null Object pattern. Instead of returning Null, or a valid transaction, the transaction::DoRefund() method returns a null object: an object that offers the same interface as the RefundTransactionResponseType instances, but its methods do nothing. With this there is no need to test whether for Null.
The should be used wisely as this can easily hide problems.
No you don't need to check for null, there. That opens up another question, though, do you really need to check for null in incoming parameters?
Remember: that's a behavior. You have to test that behavior.
But if you can't continue at that point let the exception propogate.
No, doesn't look like you should check for null here. And I also wouldn't check for null for ALL incoming parameters (as your description suggests).
It's also odd that you're returning a transactionID as a string OR the message of an exception. How will the caller of this method know if an exception happened?
If you really want to log the exception, how about something like this:
public string DoRefund(...)
{
try
{
return transaction.DoRefund(...).RefundTransactionID;
}
catch (Exception ex)
{
LogError(ex);
throw ex;
}
}
You should check for null rather than letting the exception handling handle it. As leppie said, exceptions are for exceptional conditions not normal flow of control. If you know what issues can occur then you should gracefully handle them.
Another thing to keep in mind is the performance impact of exceptions. When the exception is thrown the JVM has to unwind the call stack. In your example the exception is then also logged. All of this takes time and is much slower than a simple "if" check.
I'd suggest checking for the null then doing some kind of soft error handling instead of just letting it catch and throwing an error message.
It depends on what it means to your program when (refundResponse == null). If this has some meaning, then it makes sense to report a more informative error. If it should never happen and would indicate a flaw in the DoRefund method, then I think it's fine to allow the null to cause an exception later. In the latter case, I'd only have a specific check if you're suspicious of the method and whether it's behaving as it's supposed to.

Categories

Resources