detecting specific argument exceptions? - c#

I need to catch a specific ArgumentException.
System.ArgumentException: Input array is longer than the number of
columns in this table.
I noticed that there are a number of ArugmentExceptions that can occur, but how would I go about catching this one specifically? "Input array is longer than the number of columns in this table"
unfortunately doing catch(ArgumentException ex) is not specific enough...
We are uploading a tab delimited file and the exception above tells us to tell the user to check the number of columns in the file and to try again.

Don't catch the exception - avoid it happening in the first place. You have the input, so you know how many columns have been provided. You know the table you're adding the data to, so you know how many columns are available.
You can - and should check the validity of the data before you try to add the rows. It's as simple as that.
ArgumentException should almost never be caught and "handled". It should be an indication of the caller providing a bad argument that could have been verified beforehand. That's a programming problem, and should be fixed by adding appropriate code on the calling side.

You will have to parse/analyse the exception message, because there is no extra information available. ArgumentExceptions are typically not meant to be caught, because they indicate a programming error. That's why there's no extra information.
Note that parsing the exception message can be error prone, since your application might be rolled out to Windows machines with a different culture. In that case the .NET version might throw localized exception messages.

You'll have to catch the ArgumentException, inspect it, and if it's not the one that interests you, re-throw it.
catch(ArgumentException ex) {
if(ex.ParamName!="specificargument" || ex.Message != "Input array is longer than the number of columns in this table")
throw;
//Handle exception, inform user
}
(Different checks may be more appropriate - I.e. it may not be appropriate to check the entire message text)
It would be better if the checks for the specific type could be performed without having to re-throw exceptions that don't match - and that's exactly what exception filters were invented for. Unfortunately, C# has never surfaced this feature (despite it existing in IL, and even exposed in VB.Net)

Related

How can I extend the TRY/CATCH to handle Regular Expression Errors

I am writing a BOT that uses a lot of Regular Expressions, sometimes to get one piece of information, depending on the HTML (it gets randomised to stop people like me from finding what I want and taking it ... ) so I will go through a number of regular expressions to obtain X or Y piece of data, such as a name, score, size, weight etc etc.
Is there a way of extending the TRY/CATCH handler so that if it fails on a Regular Expression I have a catch block just for that which would let me log the expression, the HTML I was looking at, and other info without throwing the error.
It's just I have a lot of regular expressions and I don't want to set global flags before the regex execution so that if it fails in the catch, I check the global flag and if true, I know it was a regex that was being executed, so I can then log different info than if something else might have triggered it.
Or you may say that is the best way rather than overriding system code etc.
I have just come out of hospital - again, I do believe I was in there this time last year and not a single power shower on the ward worked, anyway the morphine they have given me is pretty strong so please don't blame me for a stupid question as I would have probably searched a lot more for an answer before asking for help. I am thinking that the flag way is the best way forward rather than extending code I probably shouldn't be but maybe there is already a RegEx failure catch I've missed. #
If I go the flag way I can put a generic error handler in the catch block that checks for that flag and if it finds it logs the regex, html and x y z all in my log file rather than throwing the error which I would do for other errors but with this I want a detailed error report in my log file.
Ideas?
Thanks in advance for any help.

String.Format mistyping parameters

This application tests hardware and prints the results of the test to the console. Multiple devices can be under test at once so I have multiple threads and locking around access to the console, both input and output. So I originally had this in my code right before passing the result to the function that prints:
string message = String.Format("The DUT is: {0}. The total test " +
"was a : {2}.", MAC, testResultString);
The 2 caused the application to stop executing that function. It switched control back to the other threads but never complained about an error etc so the problem took quite a while to track down. What are good strategies/best practices for dealing with String.Format since it is apparently pretty quiet when there is a problem. Or alternatives to string format that have similar flexibility.
Edit: yes the bug was tracked down and the code changed to:
string message = String.Format("The DUT is: {0}. The total test " +
"was a : {1}.", MAC, testResultString);
The point of the question is moreso how to deal with String.Format silently failing. As correctly pointed out by #alexd, this is not a problem specific to String.Format. Any function in a separate thread that throws an exception will have the same issue.
Thanks for the pointers on Re-sharper and the edits #VirtualBlackFox.
As Daniel James Bryars already said, meet ReSharper:
2 Warnings on this line as the second parameter is never used in the format string (And one error due to missing ;).
You can even with an attribute mark your own code or external code like NLog with this feature.
Warning are aggregated on the scrollbar as colored lines, available on a separate window and it can be integrated in nearly any automated system (Sonar for example)
The problem is not specific to String.Format. Pretty much any exception, thrown from a background thread, will lead to the same problem.
You may consider AppDomain.UnhandledException to catch and report such exceptions:
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
Exception x = (Exception)e.ExceptionObject;
// report error, etc.
};
But there are quite some details to be aware of, see http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception%28v=vs.110%29.aspx.
P.S. This page provides a good overview of possibilities:
WPF global exception handler
This will throw an error because {2} actually refers to the third parameter after the string. Since you only have two, it throws an exception.
string message = String.Format("The DUT is: {0}. The total test " +
"was a : {1}.", MAC, testResultString);
As long as your token references don't exceed your parameter count, you should not have to worry about error handling on a String.Format.
Why donĀ“t you try something like:
string message = String.Format("The DUT is: {0}. The total test was a : {1}.", MAC, testResultString);
I hope this helps! And SLaks says in the comment! Add a try/catch to check the exceptions ;)
If your using VS then you may need to enable those exceptions under the debug menu. String.Format does throw an exception if the number of arguments is less than any index used. Look at the MSDN page.
Update: more specifically, you need to enable exceptions from the CLR (Common Language Runtime).
In C#6 you can now use "String interpolation" (see here and here) and do something this:
string message = $"The DUT is: {MAC}. The total test " +
"was a : {testResultString}.";
and I don't know if this is compile time checked.

log4net (common.logging) erroneous exception

I have the following log4net statement in a c# application:
log.Info(CultureInfo.InvariantCulture, m => m(notice));
with the string contents of:
notice = "Checking: 645: Bp $B!!:{4V7r;K Bp $B$D$^$M$5$S (B <xxx#xxxxxx. Co. Jp> (B <xxxxx#xxxxxxx.Com>)"
causing this exception:
[Common.Logging.Factory.AbstractLogger+FormatMessageCallbackFormattedMessage]System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
at System.Text.StringBuilder.AppendFormat(IFormatProvider provider, String format, Object[] args)
at System.String.Format(IFormatProvider provider, String format, Object[] args)
at Common.Logging.Factory.AbstractLogger.FormatMessageCallbackFormattedMessage.FormatMessage(String format, Object[] args)
If you notice in the string (which, in this case, is a totally piece of garbage) there is a single bracket "{". I'm fairly certain that this is causing the exception. What can I do to avoid this? Escape the string somehow?
It's a fairly harmless exception, except that it shows up in the log file and is distracting.
It ends up that the Common.Logging log function uses the string.Format functions regardless of whether they are needed or not. So, as #HansKesting mentioned in comments, escaping any unintended brackets (braces) will be needed. So, when logging data that I suspect my have this problem, I changed the code to:
notice = notice.Replace("{", "{{");
log.Info(CultureInfo.InvariantCulture, m => m(notice));
Hopes this helps others.
You are using a self writen extention which accepts a Action as log argument. Your method m(string) causes an error. You should check the source code of your method m. Log4net it self will never cause any errors because it is designed to fail silent. If the error is caused by log4net you would have find a critical bug.
The reason log4net does not accept a Action<string> as argument is that it can have side affects like this.

Getting line number of code

Within the code I'm responsible for, I have a few 'throw new Exception()' methods flying around.
The issue is, the catch is not always in the best place or even in the same class. This means when I catch an error, I don't know where the throw originated or even if I do, there could be hundreds/thousands of lines of code in each class.
So, within the throw message, for debugging, it may be useful to state the Class Name, Project Name, Method Name and the line number for easier navigation. The line number is tricky. I can't hard code it because as soon as I amend the code it's unlikely to remain on the same line.
So, my 2 questions are
1) Do we like this idea or think no, there are better approaches!
2) Any ideas how to get the line number?
Have you considered looking at the StackTrace information found under System.Diagnostics? An example can be found at:
http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx
If you include the debugging symbols (.pdb) files, in the same directory as the .dll or .exe, it should load them automatically and provide the line number in the exception.StackTrace.
To build the symbols, in your release build settings, under Advanced Build Settings, turn Debug Info to Full
Look at the System.Diagnostics.StackFrame class for grabbing line numbers. I believe the method GetFileLineNumber may help you out
http://msdn.microsoft.com/en-us/library/system.diagnostics.stackframe
This info is usually available in the stack trace - By Jeremy (see my comments).
Sorry, not sure how to mark a comment as the right answer!?
Line numbers do not show up in code compiled in Release mode. If this is an in-house application you and you really want the line numbers you could always deploy the code compiled in Debug mode and then deploy the PDB's with the assemblies. But there is a performance cost involved in this as well so this is not always the best approach. I am not sure of any better approach at this point though.
If I remember correctly, the Roslyn project gives us a better way to get line numbers but not familiar enough with it to give more details.
You can capture the line number of a caller using C# 5.0 feature combined with default parameters. So instead of constructing and throwing the exception directly, make a method that constructs your exception.
Exception CreateMyException(
[CallerFilePath] string filePath = "",
[CallerMemberName] string memberName = "",
[CallerLineNumber] int lineNumber = 0)
{
return new Exception(string.Format("Exception thrown from line {0} in member {1} in file {2}",
lineNumber, memberName, filePath));
}
...elsewhere in your code...
throw CreateMyException(); // compiler injects current values for defaulted arguments.

c#: tryparse vs convert

Today I read an article where it's written that we should always use TryParse(string, out MMM) for conversion rather than Convert.ToMMM().
I agree with article but after that I got stuck in one scenario.
When there will always be some valid value for the string and hence we can also use Convert.ToMMM() because we don't get any exception from Convert.ToMMM().
What I would like to know here is: Is there any performance impact when we use TryParse because when I know that the out parameter is always going to be valid then we can use Convert.ToMMM() rather TryParse(string, out MMM).
What do you think?
If you know the value can be converted, just use Parse(). If you 'know' that it can be converted, and it can't, then an exception being thrown is a good thing.
EDIT: Note, this is in comparison to using TryParse or Convert without error checking. If you use either of the other methods with proper error checking then the point is moot. I'm just worried about your assumption that you know the value can be converted. If you want to skip the error checking, use Parse and die immediately on failure rather than possibly continuing and corrupting data.
When the input to TryParse/Convert.ToXXX comes from user input, I'd always use TryParse. In case of database values, I'd check why you get strings from the database (maybe bad design?). If string values can be entered in the database columns, I'd also use TryParse as you can never be sure that nobody modifies data manually.
EDIT
Reading Matthew's reply: If you are unsure and would wrap the conversion in a try-catch-block anyway, you might consider using TryParse as it is said to be way faster than doing a try-catch in that case.
There is significant difference regarding the developing approach you use.
Convert: Converting one "primitive" data in to another type and corresponding format using multiple options
Case and point - converting an integer number in to its bit by bit representation. Or hexadecimal number (as string) in to integer, etc...
Error Messages : Conversion Specific Error Message - for problems in multiple cases and at multiple stages of the conversion process.
TryParse: Error-less transfer from one data format to another. Enabling T/F control of possible or not.
Error Messages: NONE
NB: Even after passing the data in to a variable - the data passed is the default of the type we try to parse in to.
Parse: in essence taking some data in one format and transfer it in to another. No representations and nothing fancy.
Error Messages: Format-oriented
P.S. Correct me if I missed something or did not explain it well enough.

Categories

Resources