1

Suppose I write some multi-threaded C# code. (I know ... bad idea from the get-go ;) )

I have some code B, which I expect to only get called after code A has completed. I write and review my code carefully to convince myself that this is true, but I can't actually enforce that expectation, I can only check whether it is true.

So I put the checks in, and if the check ever fails, I want to throw and exception so that the developer gets a big shouty log message saying "Nope, ya fucked up; there's still an edge case where the threading doesn't do what you'd convinced yourself it did."

What's the best C# Exception type to throw here?

My instinct is to go with that old stand-by InvalidOperationException or possibly just a raw new Exception(message). But it would be nice if there were a slightly more specific type I could throw (like throwing an ArgumentException when that's the issue that's happened)

There are a few Exception types that auto-complete from Thread or Sync but they all look like they're intended for much deeper problems. i.e. there's something wrong with the actual threads. Here the thread are all fine ... it's the developer's threading logic that's in error.

Are there any sensible pre-existing Exception classes to use here?

Brondahl
  • 7,402
  • 5
  • 45
  • 74
  • Create your own exception type that models the exception being thrown. Never throw the base type `Exception`. – fredrik Mar 15 '20 at 08:48
  • Agreed. That's a fair option, if nothing better exists. My question is *does* something better exist? – Brondahl Mar 15 '20 at 08:50
  • @fredrik out-of-curiosity, what's your reason for "never throw a raw `Exception`"? What bad thing are you imaging happening? – Brondahl Mar 15 '20 at 08:51
  • If some good predefined exception exists would depend heavily on what type of error you're detecting... so it's really not possible to say without the actual error. – fredrik Mar 15 '20 at 08:53
  • 1
    Since all exceptions inherit from Exception, you cannot easily test (in a catch for example) if a thrown exception is "your" thrown exception - since an `is Exception` would match every single exception in .NET... – fredrik Mar 15 '20 at 08:54
  • `System.Threading.ThreadAbortException` possibly ? I've always found it easiest to just create your own exception when you're dealing with specific use cases, such as this. Of course most of the derived exception classes are sealed, so you have to just inherit from the base `Exception` if you go that route. – jdewerth Mar 15 '20 at 08:59
  • 1
    oh, and another reason for not throwing the base class is that [microsoft says not to](https://learn.microsoft.com/en-us/dotnet/standard/exceptions/) in their basic documentation about common exceptions... – fredrik Mar 15 '20 at 09:09
  • Maybe I am wrong, but seems like throwing an exception to tell developers/users the code is done wrong is not what `Exception` class is for. And if others don't have your source code, how would you like others to know that an edge case could cause an exception? At the end of the day, if an exception is really needed, maybe just throw `Exception`. Or if others have access to debug build etc, maybe use `Debug.Assert()` or `Debugger.Break()` when edge case happens? – weichch Mar 15 '20 at 09:25
  • 1
    @weichch It *isn't* for users :) It's just for devs during development and UAT. "IF others don't have the source code" ... then they aren't devs :D. The build we give to testers isn't a Debug build it's a candidate Release build. – Brondahl Mar 15 '20 at 09:37
  • Maybe consider `Trace.Assert` if it is release build? https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.trace.assert?view=netcore-3.1 Also see https://stackoverflow.com/questions/163538/c-sharp-what-does-the-assert-method-do-is-it-still-useful – weichch Mar 15 '20 at 09:44

1 Answers1

3

An InvalidOperationException is the most suitable built in exception for this situation.

See it's official documentation remarks section:

InvalidOperationException is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments. Typically, it is thrown when the state of an object cannot support the method call.

(emphasis mine).

Of course, there's nothing stopping you from creating your own Exception class if you want something more specific, but that would only make sense if you want the exception to carry information that doesn't fit inside the InvalidOperationException (and of course, if you do choose to create your own exception class, be sure to follow the guidlines in How to create user-defined exceptions:

  1. Derive from an existing Exception class
  2. use the word Exception as a suffix to the class name (MyVeryOwnSpecialException)
  3. Implement at least three public constructors:
    3.a: A constructor with no parameters
    3.b: A constructor that takes in a string message
    3.c: A constructor that takes in a string message and an Exception inner exception.
Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • Yeah, that's what I expected, and `be sure to follow the guidelines...` is exactly why I'm not going to bother creating my own. It's a load of complexity for no value at all. :) Sure I can't filter on my specific exception ... but I also don't want to. Maybe I will in the future, but YAGNI. Thanks for confirming my thinking! – Brondahl Mar 15 '20 at 09:50
  • Glad to help :-) This is exactly why I wrote it would only make sense of you need to carry extra information... – Zohar Peled Mar 15 '20 at 10:14