10

Is there a way to decorate a method that will do some logging, then throw an exception unconditionally, as such?

I have code like this:

void foo(out int x)
{
  if( condition() ) { x = bar(); return; }

  // notice that x is not yet set here, but compiler doesn't complain

  throw new Exception( "missed something." );
}

If I try writing it like this I get a problem:

void foo(out int x)
{
  if( condition() ) { x = bar(); return; }

  // compiler complains about x not being set yet

  MyMethodThatAlwaysThrowsAnException( "missed something." );
}

Any suggestions? Thanks.

H.B.
  • 166,899
  • 29
  • 327
  • 400
k0dek0mmand0
  • 300
  • 3
  • 10
  • What problem do you get? – Chris Ballance Oct 05 '09 at 14:51
  • "x has out attribute and hasn't been set yet at the end of method" – k0dek0mmand0 Oct 05 '09 at 14:52
  • 1
    I'm confused - how is it thrown unconditionally if it doesn't get thrown when x is set (and a return is done) – Matt Oct 05 '09 at 14:53
  • I want to mark MyMethodThatAlwaysThrowsAnException as a method that always throws an exception, not the foo method. – k0dek0mmand0 Oct 05 '09 at 14:54
  • I wonder where that answer with the guard clause went. I thought it was a better answer to just reverse the logic. – Brandon Oct 05 '09 at 14:55
  • Why use an out parameter instead of a return value? – Powerlord Oct 05 '09 at 14:56
  • he probably want's a common throw instead of duplicate code for an unset value. but that's my guess. (people need to remeber their way is not the only way) – Matthew Whited Oct 05 '09 at 14:57
  • If I understand this correctly, you're trying to refactor out duplicate code because this is a pattern you're using in multiple places. Instead of `Log("Missed Something"); throw new Exception("Missed Something")` you want a single method call. – Greg Oct 05 '09 at 15:00
  • @Greg: something like that. I also want to add a Debugger.Break statement in the MyThrow as I find it convenient. – k0dek0mmand0 Oct 05 '09 at 15:06
  • Does this answer your question? [declare a method always throws an exception?](https://stackoverflow.com/questions/3892938/declare-a-method-always-throws-an-exception) – MuiBienCarlota Dec 04 '19 at 13:54

8 Answers8

21

How about this?

bool condition() { return false; }
int bar() { return 999; }
void foo(out int x)
{
    if (condition()) { x = bar(); return; }
    // compiler complains about x not being set yet 
    throw MyMethodThatAlwaysThrowsAnException("missed something.");
}
Exception MyMethodThatAlwaysThrowsAnException(string message)
{
    //this could also be a throw if you really want 
    //   but if you throw here the stack trace will point here
    return new Exception(message);
}
Matthew Whited
  • 22,160
  • 4
  • 52
  • 69
4

It's a very old thread but I just want to add you should write it different from the start:

void foo(out int x)
{
    if (!condition()) 
        MyMethodThatAlwaysThrowsAnException("missed something.");

    x = bar();
    // and so on...
}

That way compiler won't complain and your code is much more clear.

2

If you know the exception will always be thrown, why does it matter. Just set the variable to something so it can compile:

void foo(out int x)
{
  if( condition() ) { x = bar(); return; }

  x = 0;

  MyMethodThatAlwaysThrowsAnException( "missed something." );
}
Dan Herbert
  • 99,428
  • 48
  • 189
  • 219
2

There's no way of marking a method in this way.

Possibly irrelevant, but the pattern in your example, using an out parameter, is a bit odd. Why not just have a return type on the method instead?

int Foo()
{
    if (condition()) return bar();

    MyMethodThatAlwaysThrowsAnException("missed something.");
}
LukeH
  • 263,068
  • 57
  • 365
  • 409
  • That was just a simple example. The actual code is rather more complex. – k0dek0mmand0 Oct 05 '09 at 14:57
  • @k0dek0mmand0: I suspected that might be the case. I guess you're out of luck - there's no way to tell the compiler that `MyMethodThatAlwaysThrowsAnException` always throws. – LukeH Oct 05 '09 at 14:59
1

x is an out parameter and must be set before you move forward

Chris Ballance
  • 33,810
  • 26
  • 104
  • 151
1

If you don't want to have to set x, why don't you just use a ref parameter instead?

void foo(ref int x)
{
  if( condition() ) { x = bar(); return; }

  // nobody complains about anything

  MyMethodThatAlwaysThrowsAnException( "missed something." );
}
Maximilian Mayerl
  • 11,253
  • 2
  • 33
  • 40
1

To mark method as always throwing you can use [DoesNotReturn] attribute.

Attribute description: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.doesnotreturnattribute?view=net-6.0

Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/nullable-analysis#stop-nullable-analysis-when-called-method-throws

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
karolgro
  • 181
  • 1
  • 8
0

It doesn't answer your question but when using out parameters it is always a good idea to initialize them in the beginning of the method. This way you won't have any compiler errors:

void foo(out int x)
{
    x = 0;
    if( condition() ) { x = bar(); return; }
    MyMethodThatAlwaysThrowsAnException( "missed something." );
}
Matthew Whited
  • 22,160
  • 4
  • 52
  • 69
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 4
    I think out parameters should be assigned where it makes sense or as it may prevent some hidden bugs at compile time just because you forgot to assign out parameter at some code path. – Dzmitry Huba Oct 05 '09 at 14:57