This really, really urks me, so I hope that someone can give me a reasonable justification for why things are as they are.
NotImplementedException. You are pulling my leg, right?
No, I'm not going to take the cheap stab at this by saying, "hang on, the method is implemented - it throws a NotImplementedException." Yes, that's right, you have to implement the method to throw a NotImplementedException (unlike a pure virtual function call in C++ - now that makes sense!). While that's pretty damn funny, there is a more serious problem in my mind.
I just wonder, in the presence of the NotImplementedException, how can anyone do anything with .Net? Are you expected to wrap every abstract method call with a try catch block to guard against methods that might not be implemented? If you catch such an exception, what the heck are you supposed to do with it??
I see no way to test if a method is actually implemented without calling it. Since calling it may have side effects, I can't do all my checks up-front and then run my algorithm. I have to run my algorithm, catch NotImplementedExceptions and the some how roll back my application to some sane state.
It's crazy. Mad. Insane. So the question is: Why does the NotImplementedException exist?
As a preemptive strike, I do not want anyone to respond with, "because designers need to put this in the auto-generated code." This is horrid. I would rather the auto-generated code not compile until you supply an implementation. For example, the auto generated implementation could be "throw NotImplementedException;" where the NotImplementedException is not defined!
Has anyone ever caught and handled a NotImplementedException? Have you ever left a NotImplementedException in your code? If so, did this represent a time bomb (ie, you accidentally left it there), or a design flaw (the method should not be implemented and will never be called)?
I'm very suspicious of the NotSupportedException also... Not supported? What the? If it's not supported, why is it part of your interface? Can anyone at Microsoft spell improper inheritance? But I might start another question for that if I don't get too abuse for this one.
Additional info:
This is an interesting read on the subject.
There seems to be a strong agreement with Brad Abrams that "NotImplementedException is for functionality that is just not yet implemented, but really should (and will be). Something like what you might start with when you are building a class, get all the methods there throwing NotImplementedException, then flush them out with real code…"
Comments from Jared Parsons are very weak and should probably be ignored: NotImplementedException: Throw this exception when a type does not implement a method for any other reason.
The MSDN is even weaker on the subject, merely stating that, "The exception that is thrown when a requested method or operation is not implemented."
If you don't want to use it then just ignore it. If you have a block of code whose success depends on every piece of it succeeding, but it might fail in between, then your only option is to catch the base
Exception
and roll back what needs to be rolled back. ForgetNotImplementedException
. There could be tons of exceptions thrown, likeMyRandomException
andGtfoException
andOmgLolException
. After you originally write the code I could come by and throw ANOTHER exception type from the API you're calling. One that didn't exist when you wrote your code. Handle the ones you know how to handle and rollback for any others i.e.,catch(Exception)
. It's pretty simple, I think... I find it comes in handy too. Especially when you're trying fancy things with the language/framework that occasionally force things upon you.One example I have is serialization. I have added properties in my .NET library that don't exist in the database (for example, convenient wrappers over existing "dumb" properties, like a
FullName
property that combinesFirstName
,MiddleName
, andLastName
). Then I want to serialize these data types to XML to send them over the wire (for example, from an ASP.NET application to JavaScript), but the serialization framework only serializes public properties with bothget
andset
accessors. I don't want you to be able to setFullName
because then I'd have to parse it out and there might be some unforeseen format that I wrongly parse and data integrity goes out the window. It's easier to just use the underlying properties for that, but since the language and API require me to have aset
accessor, I'll throw aNotImplementedException
(I wasn't aware ofNotSupportedException
until I read this thread, but either one works) so that if some programmer down the road does try to setFullName
he'll encounter the exception during testing and realize his mistake.Well, I somewhat agree. If an interface has been made in such a way that not all class can implement all bits of it, it should've been broken down in my opinion.
If IList can or cannot be modified, it should've been broken down into two, one for the unmodifiable part (getters, lookup, etc.), and one for the modifiable part (setters, add, remove, etc.).
From ECMA-335, the CLI specification, specificialy the CLI Library Types, System.NotImplementedException, remarks section:
"A number of the types and constructs, specified elsewhere in this Standard, are not required of CLI implementations that conform only to the Kernel Profile. For example, the floating-point feature set consists of the floating-point data types System.Single and System.Double. If support for these is omitted from an implementation, any attempt to reference a signature that includes the floating-point data types results in an exception of type System.NotImplementedException."
So, the exception is intended for implementations that implement only minimal conformance profiles. The minimum required profile is the Kernel Profile (see ECMA-335 4th edition - Partition IV, section 3), which includes the BCL, which is why the exception is included in the "core API", and not in some other location.
Using the exception to denote stubbed methods, or for designer generated methods lacking implementation is to misunderstand the intent of the exception.
As to why this information is NOT included in the MSDN documentation for MS's implementation of the CLI is beyond me.
Re
NotImplementedException
- this serves a few uses; it provides a single exception that (for example) your unit tests can lock onto for incomplete work. But also, it really does do what is says: this simply isn't there (yet). For example, "mono" throws this all over the place for methods that exist in the MS libs, but haven't been written yet.Re
NotSupportedException
- not everything is available. For example, many interfaces support a pair "can you do this?" / "do this". If the "can you do this?" returns false, it is perfectly reasonable for the "do this" to throwNotSupportedException
. Examples might beIBindingList.SupportsSearching
/IBindingList.Find()
etc.Most developers at Microsoft are familiar with design patterns in which a NotImplementedException is appropriate. It's fairly common actually.
A good example is a Composite Pattern, where many objects can be treated as a single instance of an object. A component is used as a base abstract class for (properly) inherited leaf classes. For example, a File and Directory class may inherit from the same abstract base class, because they are very similar types. This way, they can be treated as a single object (which makes sense when you think about what files and directories are - in Unix for example, everything is a file).
So in this example, there would be a GetFiles() method for the Directory class, however, the File class would not implement this method, because it doesn't make sense to do so. Instead, you get a NotImplementedException , because a File does not have children the way a Directory does.
Note that this is not limited to .NET - you'll come across this pattern in many OO languages and platforms.
Two reasons:
Methods are stubbed out during development, and throw the exception to remind the developers that their code writing is not finished.
Implementing a subclass interface that, by design, does not implement one or more methods of the inherited base class or interface. (Some interfaces are just too general.)