I have some data I am deserializing inside a Linq statement:
var scheduledData = results
.Where(o => o.Result.IsValid)
.SelectMany(o => JsonConvert.DeserializeObject<List<CalendarJob>>(o.Result.Response))
.ToList();
This is throwing an error. I never see this error in the debugger. The returned web page lists a 500 error showing this. So I added some handing:
var scheduledData = results
.Where(o => o.Result.IsValid)
.SelectMany(o => {
try {
return JsonConvert.DeserializeObject<List<CalendarJob>>(o.Result.Response);
}
catch {
return new List<CalendarJob>();
}
})
.ToList();
Yes this is really ugly. I only did this so I could put a breakpoint on the catch block so I could inspect some values. This is not code I would leave in place! :)
I put a breakpoint on the return statement inside the try block and also the catch block. Then I execute the code. The try statement hits and execution is gone. The catch block never fires nor does any other code in my method.
Should this catch block be allowed in linq? I sure thought so?
Yes, I am in debug mode. Yes, I have cleaned and rebuilt. The breakpoint on my try block does indeed hit. I can inspect the value of the string about to be deserialized and the value is not right. It's "". I do not mean string.Empty, I specifically mean the string contains two bytes and both are the double quote character. The service I am getting the data from is not returning good data. But my catch block never fires.
One more thing to note. I put the entire thing into a try...catch block and that catch block does hit. Only the one inside LINQ does not.
Yes - this will work the way you think it will.
The only time it won't work will be an exception you cannot catch, like a StackOverflowException.
To prove it, just execute the folllowing code in Visual Studio, or Linqpad and observe the breakpoint is hit twice.
var list = new List<string>
{
"a",
"b"
};
list.Select(i =>
{
try
{
return int.Parse(i);
}
catch
{
return 0; // Put a breakpoint here.
}
}).ToList();
I found the cause. Internally JsonConvert doesn't throw an error with invalid Json. Instead it returns null. So my try...catch block around the JsonConvert didn't do anything because there was nothing to catch. Next, SelectMany was expecting a List<> item back and tried to enumerate it to select the elements out of it. Because it received null, the error was thrown here and not inside the Json conversion. This is why the outer try...catch picks up the error but the one in the OP above does not.
I accepted RB's answer because he answers my original question. This is simply an explanation for any future finders.
So, if I had something like this:
try
{
variable = Image.FromFile("Image1");
variable2 = Image.FromFile("Image2");
variable3 = Image.FromFile("Image3");
}
catch (Exception e) { }
What would happen if the second line threw an exception? Would variable 1 be assigned correctly and not 2 or 3? Or would it attempt to do 3 after handling the exception?
Since all variables are local (scoped) to the try block, it really does not matter because you can not access any of the variables outside of the block.
When an Exception is encountered control is transferred to the inner-most catch, there is no way to ignore it and continue at the next statement.
Update
With your changes, if the 2nd FromFile throws, then variable will have an Image. variable2/3 will see no change (so most likely will null).
It falls out after the 2nd statement if that one throws. The first statement would succeed. The 3rd would never be evaluated.
Like the other poster said, it doesn't matter in this case since the variables are local and the ReadFromFile doesn't have side effects.
The first variable named variable would successfully have a value assigned to it.
The exception is thrown on line two and anything after that is discarded but anything prior will execute. So to simplify this further:
1st statement executes .
2nd throws exception value is not stored in variable.
3,4,5... won't execute.
If you had a try/catch/finally then the finally will always execute.
If you want more in-depth breakdown of how exception handling works take a look at this article.
http://www.codeproject.com/Articles/125470/Exception-Handling-for-C-Beginners
I'm running the following code:
hashedUrlDataList.Select(mDalHashedUrlData.Save);
I have put a breakpoint in the called delegate,
public HashedUrlData Save(HashedUrlData item)
{
//breakpoint here
}
but it doesn't stop there.
How can I fix this?
Your method will be called when you'll enumerate the result of Select() not when declared.
Enumerable.Select is Lazy.
Try this and tell me if your break point is caught
hashedUrlDataList.Select(mDalHashedUrlData.Save).ToList();
Or the basic:
hashedUrlDataList.Select(mDalHashedUrlData.Save).GetEnumerator().MoveNext()
It just works if you have at least one element.
You can do it too:
hashedUrlDataList.Select(mDalHashedUrlData.Save).Any();
Any() do the same that GetEnumerator().MoveNext()
I think that what you want is:
List<HashedUrlData> hashedUrlDataList = new List<HashedUrlData>();
hashedUrlDataList.ForEach(Save);
LINQ is for querying data; it's not intended to cause side-effects.
If you're more interested in the side efects of your Savemethod than the HashedUrlData instance it returns, you should really be calling
foreach (HashedUrlData h in hashedUrlDataList)
{
h.Save();
}
If you will eventually be using the returned values and this is just an intermediate/debugging stage, then by all means use LINQ. Just be aware that Save will only be called as you access each returned value, or call something else that enumerates the whole enumerator as the other answers have shown.
In the example code below I am taking a list of strings and concatenating them to a delimited string. The problem occurs when I use the setter with an empty list. The ToString method throws an ArgumentOutOfRangeException since the second parameter is a -1.
How should conditions (exceptions thrown in getters/setters) like this be handled?
I don't like the fact that the setter throws an exception since the caller doesn't know about the internals of the class and therefor should not have to handle (or even know how) the exception. Catching all exceptions in the getter/setter and quietly handling them also sounds like a bad idea since the caller will not know the getter/setter failed.
//I realize that this isn't the best code but I wanted to produce an example
//to demonstrate my question.
private string theStringVariable;
const string DELIMITER = ",";
public IList<string> StringList
{
set
{
StringBuilder stringBuilder = new StringBuilder();
foreach(string entry in value)
{
stringBuilder.Append(entry);
stringBuilder.Append(DELIMITER);
}
theStringVariable = stringBuilder.ToString(0, stringBuilder.Length - 1);
}
}
You should check for the potential, common error conditions, and throw your own exception (prior to the StringBuilder errors) right up front, with a meaningful error message.
In your case, you'll most likely want to use some form of ArgumentException if the setter is called with an Empty string list. The key here is that your exception can say "the argument contained an empty collection" instead of "index out of bounds", which is going to make the caller understand, immediately, why they have a "real" problem in their call.
On a side note: In cases like the code you posted - I'd also consider making this a method instead of a property. You're doing quite a bit of "work" in this property setter, which is going to be somewhat unexpected. By making this a method, you'll be giving the user a clue that there's a bit of "processing" occurring within this property...
I don't think your issues deal with best practices.
The best practice you need to watch in your case is the line that says
stringBuilder.ToString(0, stringBuilder.Length - 1);
You are causing the exception to be thrown by not checking the string length. If your length is 0, just return empty string.
If we are talking in generalities, if you have the ability to code around common issues, empty sets, badly formatted data, then you should do your best to shield the user from unnecessary errors.
However* sometimes it is better to abruptly/loudly fail then it is to silently fail.
First of all, if you can spot someone that might cause an exception --- fix it so the exception doesn't happen. In this case, check for an empty list before the loop and set the varaible appropriately.
Otherwise, catch the exceptions (the one you expect might happen(*)), an throw a new more appropriate exception (with the original as the inner exception)
(*) Catch only the one's you expect might happen -- let the unexpected one bubble up to the user.
Code Complete suggests if you can handle the exception locally that you do so: "Don't use an exception to pass the buck". In the example given this would mean check for an empty value and handle this appropriately in the setter.
My question is pretty vague :o) - But here is an example :
When I was writing C code, I was able to log counter's value when something failed :
<...>
for ( int i = 0 ; i < n ; i++ )
if ( SUCCESS != myCall())
Log( "Failure, i = %d", i );
<...>
Now, using exceptions, I get this :
try
{
<...>
for ( int i = 0 ; i < n ; i++ )
myCall();
<...>
}
catch ( Exception exception )
{
Log( "Failure ! Maybe in myCall() ? Don't know. i's value ? No clue." );
}
Of course, one may declare "i" outside of the try/catch statement (and this is what I'm doing). But I don't like it - I like declare variable where they are used, not before.
But maybe am I missing something here. Do you have any elegant solution ?
Thank in advance !
Sylvain.
ADDED : myCall() is an obscure API call - I have no clue what it can throw. Also, I can of course add a Try/Catch block around each call, but I would then be better to use return codes ? Would I then add a lot of noise around important lines of code ?.
how about:
for(int i = 0; i < n; i++)
{
try
{
myCall();
}
catch(Exception e)
{
Log(String.Format("Problem with {0}", i));
}
}
I think you've got it wrong, and its not surprising as many other people do too.
Exceptions are not to be used for program flow. Read that again, its important.
Exceptions are for the "whoo, that's wasn't supposed to happen" errors that you hope never to see at runtime. Obviously you will see them the moment your first user uses it, which is why you have to consider the cases where they might happen, but you should still not try to put code in to catch, handle and continue as if nothing had happened.
For errors like that, you want error codes. If you use exceptions as if they were 'super error codes' then you end up writing code like you mentioned - wrapping every method call in a try/catch block! You might as well return an enum instead, its a lot faster and significantly easier to read error return code than litter everything with 7 lines of code instead of 1. (its also more likely to be correct code too - see erikkallen's reply)
Now, in the real world, it is often the case that methods throw exceptions where you'd rather they didn't (EndOfFile for example), in which case you have to use the "try/catch wrapper" anti-pattern, but if you get to design your methods, don't use exceptions for day-to-day error handling - use them for exceptional circumstances only. (yes, I know its difficult to get this kind of design right, but so is much of design work)
I don't like the "now, with exceptions..." expression.
Exceptions are a tool that you have for using it in your programming - if you think that it is the best option, use it, otherwise, don't.
I follow a personal rule of not throw any exceptions that I can avoid throwing, in internal code. For an API of a publicly available DLL, precondition checks should be left enabled and trigger exceptions if they fail, yes; but for internal logic, I seldom (if ever) include exceptions in my design. Conversely, when I'm using some function that documents that it will throw if some bad situation happens, I tend to capture the exception inmediately - it is an expected exception, after all.
If you think that your non-exceptional alternative is better - stick to it!
Yeah. 2 things.
Put the try-catch blocks where they make sense. If you're interested in exceptions from myCall (as well as i's value) then use
for ( int i = 0 ; i < n ; i++ )
try { myCall(); } catch ( Exception exception ) {
Log( "Failure, i = %d", i );
}
Throw objects of different classes for different errors. If you're interested in logical errors occurring in financial processing, throw finances::logic_error, not std::exception("error msg") or something. This way you can catch what you need.
Two things here, from my perspective.
It's not outrageous to expect the exception itself to contain information about the value of i, or less specifically about the context it was evaluated in and what went wrong. For a trivial example, I would never just throw a straight InvalidArgumentException; rather, I would ensure I passed an accurate description into the constructor, such as
public void doStuff(int arg) {
if (arg < 0) {
throw new InvalidArgumentException("Index must be greater than or equal to zero, but was " + arg);
}
...
This might not expilictly log the value of i, but in most cases you're going to be able to understand what the problem was with your input that caused the error. This is an argument in favour of exception chaining too - if you catch, wrap and rethrow exceptions at every conceptual level, then each wrapping can add its own relevant variables that are too high up to be seen or understood by the fundamental low-level error.
Alternatively, if things are really too abstracted for your myCall function to know what is going on, then I find that logging at a higher verbosity level before making the call works well, e.g.
try
{
<...>
for ( int i = 0 ; i < n ; i++ )
DebugLog("Trying myCall with i = " + i);
myCall();
<...>
}
catch ( Exception exception )
{
Log( "Failure ! Maybe in myCall() ? Don't know. i's value ? No clue." );
}
This way, if something does go wrong you can inspect your high-verbosity debug log and find what i was just before the call that threw the exception.
Consider the opinions of Raymond Chen as well as Microsoft's x64-thinking.
(( raymond chen exceptions )) as a Google-query is enough to get you to his classic essays "Cleaner, more elegant, and wrong -- Just because you can't see the error path doesn't mean it doesn't exist." and the clarification "Cleaner, more elegant, and harder to recognize".
(( x64 exception model )) gets you to the MSDN article "Everything You Need To Know To Start Programming 64-Bit Windows Systems", which contains the quote "The downside to table-based exception handling (relative to the x86 stack-based model) is that looking up function table entries from code addresses takes more time than just walking a linked list. The upside is that functions don't have the overhead of setting up a try data block every time the function executes."
To summarize this quote, in x64 it is free or nearly-free to setup a "catch" which is never used, but to actually throw-catch an exception is slower than in x86.
It can be more elegant, if the object that you throw, can hold the context information that tells you something about the nature of the error.
Derive a throwable object from an istream, and you can use >> to stream information into it.
teach the object how to display itself <<.
When you detect an error condition, in the level below, or N levels below. Fill up your object with good context information, and throw it. When you catch the object, tell it to display its context information to the log file, and/or the screen and/or whereever you want it to.
Of course, one may declare "i" outside of the try/catch statement (and this is what I'm doing).
Well … if you really need to know the value of i then this seems like a logging vehicle – structured exception handling probably isn't the best way then. If you want to handle the exception conditionally (i.e. only when debugging), put the try block inside the loop. Since this may hurt performance (depending on your environment), only do this in debug mode.
First things, first. If you are trapping Exception you are wrong. You should be trapping the specific exception you are expecting.
But that aside, if your exceptions are being thrown by your own code, you can use intelligent exceptions to encompass all the data you need to know about that exception.
For instance, an ArrayIndexOutOfBoundsException will contain the index addressed.
You can get more specific information in two ways. First, don't catch Exception, catch a specific exception. Second, use multiple try/catch statements in a function where you need to be sure which function call threw the exception.
In my opinion, exceptions shouldn't be used in such a case, but if you really need them, I'd go the following way:
You could pass the 'i' as a parameter to the myCall(); function and if any error occured, some special exception would be thrown. Like:
public class SomeException : Exception
{
public int Iteration;
public SomeException(int iteration) { Iteration = iteration; }
}
The loop block:
try
{
for(int i = 0; i < n; ++i)
{
myCall(i);
}
}catch(SomeException se)
{
Log("Something terrible happened during the %ith iteration.", se.Iteration);
}
And finally the myCall() function:
void myCall(int iteration)
{
// do something very useful here
// failed.
throw new SomeException(iteration);
}
We lose the possibility to easily see how the code will handle failures in different places. Raymond Chen has written a good article about it
Well! you could do this:
try
{
<...>
for ( int i = 0 ; i < n ; i++ )
try {
myCall();
} catch(Exception e) {
println("bloody hell! " + i);
}
<...>
}
I think Exceptions are cooler than Java shows it to you. What is really fun is to have the debugger come up on every exception that isn't handled and then take a look at the stack at the moment of failure, so that you can examine i without having to change a line of code. That is, I believe, what exceptions should be for.
Many exception handling tools (MadExcept for Delphi is one) allow you to retrieve the entire stack trace when you catch the exception. So, you'd know exactly where it was thrown.
The common technique for getting "i" is to catch the exception, and add extra data to it (the istream technique) before rethrowing it. It's rare that this is necessary, but if you insist...