C# Extension Methods for Generic Functions - c#

I want to create a simple one-line try/catch without all the extra fluff:
// The extension class
public static class TryExFunc
{
public static Exception TryEx<TResult> (this Func<TResult> func,
out TResult result)
{
Exception error = null;
try
{
result = func();
}
catch(Exception ex)
{
error = ex;
result = default(TResult);
}
return error;
}
}
// My Error Prone Function
public string SayHello() { throw new Exception(); }
// My Code
// One (ok, two) line(s) to try/catch a function call... ew, works, but ew
string result;
Exception error = ((Func<string>)SayHello).TryEx<string>(out result);
// I want to do this!!!
string result;
Exception error = SayHello.TryEx<string>(out result);
Is there a way that I can do the bottom example? I'm still learning C# (coming from Lua and C++ background). Lua has a really nice function called 'pcall' that basically does the same thing. Thanks for any advice or suggestions you have!
:)

You can't. Because the method group has no type. It's convertible to different delegate types. So you have to cast it to a delegate type before using it.
If you want to avoid cast you can do:
Func<string> sayHello = SayHello;
Exception error = sayHello.TryEx<string>(out result);

It doesn't work as an extension method because in order to use an extension method, C# first needs to know the type to extend and, as #Selman22 stated, SayHello is a method group which may have other overloads, so we don't know the type.
It works as a method call because C# can see that the parameter required is a Func<T> and that SayHello is a valid Func<T>
The format below works to call the function.
string result;
Exception error = TryExFunc.TryEx(SayHello, out result);
and I do agree with #Enigmativity that you probably shouldn't be treating exceptions this way.

Related

Is there a way of getting the compiler to initialize a string with the enclosing method name?

Our C# codebase have several methods that create error messages that include the method's name. Can I get the compiler to statically insert the method name for me? I know I could do something with reflection, but I'd rather not.
Amongst other things, I'm seeing quite a few copy-paste errors where the exception handling from one method is copied to another, without the method name changing.
public void Method1()
{
try
{
DoStuff();
}
catch (Exception e)
{
HandleError("Method1", details);
}
}
Rather than include the string "Method1" (and "Method2" up to "Methodn") is there a way of telling the compiler to insert the current method name there?
In NET 4.5 you can use the CallerMemberName attribute. Your HandleError method would then look like so:
void HandleError(YourDetailsClass details,
[CallerMemberName] callingMethod = null)
and you'd simply use
HandleError(details);
you can use MethodBase.GetCurrentMethod which returns MethodInfo
using System.Reflection;
and then
catch (Exception e)
{
HandleError(MethodBase.GetCurrentMethod().Name, details);
}
Yes, you can try with this:
System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
string methodName = st.GetFrame(0).GetMethod().Name;
And you will have the name of your running method.
One way is to use the StackTrace and StackFrame classes in System.Diagnostics to retrieve the method name:
private void HandleError(Exception ex) {
var st = new StackTrace ();
var sf = st.GetFrame (1); // get the previous method that called this
// (not this method)
var previousMethod = sf.GetMethod ();
var errorMessage = string.Format("Error in method {0} with Exception {1}",
previousMethod.Name,
ex.Message);
}
Example:
void MyMethod() {
HandleError(new Exception("Error here"));
}
errorMessage would contain: Error in method MyMethod with Exception Error here.

Get name of last called method

I have the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
try
{
this.CheckValue(true); // call method
}
catch(Exception ex)
{
// how to get here name of last called method
}
}
public int CheckValue(bool sender)
{
var qwe = int.Parse("qwe"); // invoke an exception
return 0;
}
}
I need to get in "catch block" name of last called method (in this case "CheckValue"), but it return that called method is "StringToNumber".
I try to get it using StackTrace:
stackTrace.GetFrame(1).GetMethod().Name; -> "Main"
MethodBase.GetCurrentMethod(); -> "Void .ctor()"
ex.TargetSite.Name; -> "StringToNumber"
It's possible to do this?
Short Answer:
Yes, You can!!!
I'd just play around with Extension Methods and the trick here, is to get the last frame of the desired class, otherwise it would get methods of mscorlib assembly. So here it go:
public static string GetLastCalledMethod<T>(this Exception ex)
{
var stackTrace = new System.Diagnostics.StackTrace(ex);
var lastFrame = stackTrace.GetFrames().FirstOrDefault(frame => frame.GetMethod().DeclaringType.FullName == typeof(T).FullName);
string methodName = string.Empty;
if (lastFrame != null)
methodName = lastFrame.GetMethod().Name;
return methodName;
}
Short Answer:
You can't.
Long Answer:
If you really need to do that, you will need to perform logging code in all the methods you want to track.
You can create a global variable (ugh) to store a MethodInfo with the last called method, and inside every method, set it to MethodBase.GetCurrentMethod(). Then whenever you want, you can examine that variable to see which method set it last.
In your case, you probably are trying to determine which method the exception was thrown in. You are looking at TargetSite, which returns the lowest method in the hierarchy, whereas you seem to want the one immediately below the current method. If simply examining Exception.StackTrace doesn't provide enough information, you might be able to parse out information from StackTrace and use reflection to get a MethodInfo. Usually, the StackTrace is good enough.
You may also be able to throw a new exception in the top-level method, so you can get the TargetSite from the new one.
Summary:
If Exception.StackTrace doesn't provide enough information, then you will either have to:
Perform logging code in each method you want to check for.
Parse out what information you can get from the Exception.
Change the exception throwing scheme to throw a new exception with InnerException set to the original exception.
I don't know why you want to do this.. because this is expected behaviour. The site of the exception is what you're being shown.. within the int.Parse() calls.
That being said.. if you really want to do this, you need to wrap a try.. catch in CheckValue, and re-throw the exception from there, but in a way that breaks the call stack.. like so:
public int CheckValue(bool sender) {
try {
var qwe = int.Parse("qwe"); // invoke an exception
return 0;
}
catch (Exception ex) {
throw ex; // this breaks the call stack and re-throws the exception from here..
}
}
Then, ex.TargetSite.Name == "CheckValue". I'm still not sure why you'd want to do this.. as a stack trace will actually show you where it all unwinds from after failure.

Specifying that a function does not return in C#

Is there any way to tell the C# compiler that a function never returns? I'm running into the following problem. This is a boiled down version for simplicity.
public int myMethod()
{
try
{
return anythingHere();
}
catch
{
Environment.Exit(1); //or a function which always either calls Environment.Exit or throws an exception
}
}
'package.class.myMethod()' not all code paths return a value.
If not, is there a general way to frame this sort of thing other than inserting unreachable code? Having a 'return 0' or somesuch after the Exit just seems ridiculous to me. As far as I know there is no way that a function can return from an Environment.Exit call, so no return value is needed if that branch is taken (if it threw an exception the function still wouldn't need to have returned a value).
EDIT:
Maybe something like this?
public T MyExit<T>()
{
Environment.Exit(1);
return default(T);
}
Still not entirely satisfactory though.
C# does not support this.
In fact, it is impossible to do this in the general case.
Make the method void, and pass in an object that contains the 'anythingHere' type of information you need as an out type, so that it can be set, but the method itself won't actually return anything.
public void myMethod(out anythingObject)
{
try
{
anything = new anythingObject(stuff goes here);
}
catch
{
Environment.Exit(1); //or a function which always either calls Environment.Exit or throws an exception
}
}
I'm not sure if it's what you're looking for, but this would avoid unreachable code:
public int myMethod()
{
int retVal = 0;
try {
retVal = anythingHere();
} catch {
Environment.Exit(1);
}
return retVal;
}
It might be better to throw an exception than to call Environment.Exit. If someone else used your class, and their process suddenly shut down, they'd be pretty surprised. By throwing an exception you can at least explain why the problem happened.
At the top level entry point of your app (i.e., Main) you could then set up a global exception handler (AppDomain.UnhandledException) that handles all exceptions and calls Environment.Exit.
Make it a void, instead of an int.
public void myMethod(out int i)
{
try
{
i = anythingHere();
}
catch
{
Environment.Exit(1);
}
}

C# Function cannot return -- prevent compiler warning

I have a function that is guaranteed never to return. It logs data and throws an exception.
public int f()
{
... do stuff ...
if(condition)
BadUserData.Throw(... parameters...);
else
return 0;
}
I get the error message "not all code paths return a value. I can fix this of course by a dummy return after the non returning function, but I wonder if there is an attribute or something I can apply to the Throw function it indicate that it never returns? I had a look and could not find one.
No, there isn't. Actually, to get the most appropriate call stack, I would have something more like below, where the method creates the exception but we throw it locally:
if(condition)
throw BadUserData.CreateSomeFormOfException(... parameters...);
which solves both problems in one go.
Another lazier approach would be:
if(condition) {
// throws <===== comments are important here ;p
BadUserData.Throw(... parameters...);
}
return 0;
Well instead of BadUserData.Throw actually throw:
public int f()
{
... do stuff ...
if(condition)
throw new Exception("... parameters...");
else
return 0;
}
or have this method return an Exception and then:
throw BadUserData(... parameters...);
Other than that, no, there aren't any attributes or anything that will make your code to compile.
If the method's job is to log and then throw and exception, you sould change the method signature to be
public void f()
instead of
public int f()
This will take care of your compiler issue. It's also going to be a lot cleaner as you can omit the else section of the method body.
Return the exception in BadUserData.Throw instead of throwing it and do:
public int f()
{
... do stuff ...
if(condition)
throw BadUserData.Throw(... parameters...);
else
return 0;
}
I guess you have no other choice than adding a return statement with a dummy value, e.g. return -1;.

if statement for throwing Exception?

Hi I wanted to ask because I'm not sure if is it propriete using of Exception:
public int Method(int a, int b) {
if(a<b) throw new ArgumentException("the first argument cannot be less than the second");
//do stuff...
}
can I throw Exception after if statement? or should I always use try - catch when it goes with the exceptions?
That is perfectly valid. That is exactly what exceptions are used for, to check for "Exceptions" in your logic, things that weren't suppose to be.
The idea behind catching an exception is that when you pass data somewhere and process it, you might not always know if the result will be valid, that is when you want to catch.
Regarding your method, you don't want to catch inside Method but infact when you call it, here's an example:
try
{
var a = 10;
var b = 100;
var result = Method(a, b);
}
catch(ArgumentException ex)
{
// Report this back to the user interface in a nice way
}
In the above case, a is less than b so you can except to get an exception here, and you can handle it accordingly.
In this case, you don't want to catch the exception. You're throwing it to alert the caller that they've made a mistake in the way they called your method. Catching it yourself would prevent that from happening. So yes, your code looks fine.
That's perfectly fine. You're throwing the exception, not catching/handling it, so you wouldn't need a try/catch block for it.
This is perfectly valid, you can use the same construct even with the constructors.
But What you should not do is
public int Method(int a, int b)
{
try
{
if (a < b)
throw new ArgumentException("the first argument cannot be less than the second");
}
catch (Exception)
{
}
return 0;
}
You've got the right idea. You could use your code like this:
void MyMainMethod()
{
// ... oh, let's call my Method with some arguments
// I'm not sure if it'll work, so best to wrap it in a try catch
try
{
Method(-100, 500);
}
catch (ArgumentException ex)
{
Console.WriteLine(ex.Message);
}
}
public int Method(int a, int b)
{
if (a < b) throw new ArgumentException("the first argument cannot be less than the second");
//do stuff ... and return
}
It might help to look through MSDN's Handling and Throwing Exceptions and Best Practices for Handling Exceptions
What you've done here is perfectly Ok.
A common pattern for arg checks is to wrap the check/throw code in a static "Contract" class ensuring you have a consistent approach to exception management when validating input arguments.
Slightly off topic but if using .NET 4.0 you can also look at the new Code Contracts feature for validation of method input and output.
All above answers are correct but I like to mention one additional point here which I did not see mentioned in any of the answers. The reason why you should throw an exception and not return an integer e.g. 0 or -1 for signalling that an error occurred, is that the returned integer can be mistakenly treated/assumed as a valid result of your method. It is an integer anyway, and your method, after performing its internal logic returns an integer. So the caller of this method can mistakenly treat any returned integer as a valid result, which can lead to bugs down the line. In that case, throwing an exception makes perfect sense.

Categories