Amazon.com Widgets

The difference between NotSupportedException and NotImplementedException

Sounds like one of those Wait Wait Don’t Tell me questions… 10 points if you can tell me the difference between NotSupportedException and NotImplementedException... ;-)

 

NotSupportedException is for cases where it is ok (that is, by design) to not implement some interface functionality (for example IList.Add(), because IList offers a way to check to see if Add() will throw.  

 

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…

 

Clear as mud? 

 

Now comes the part where you tell me the places in the framework we are not following these guidelines and I have to go off an beat up a bunch of different teams.  ;-)

Published 29 July 04 09:57 by BradA

Comments

# Eric Newton said on July 29, 2004 10:40 PM:
I'd like to see the NotImplementedException to somehow tag the method in the Task List as "Need to be implemented"

or I guess in Whidbey you could make a code block whatever thing to add the TODO and the NotImplementedException

An MSDN article outlining proper Exception "etiquette" would be good:
- all exceptions should inherit from ApplicationException?
- all exceptions should implement Serialization support, maybe through a "build exception" code template when you say "Add Item > Exception class"
- some recommended practices, ie a project level Exception class inheriting from ApplicationException, then subsequent project specific Exceptions all derived from the Project Exception class, obviously within reason.
# Ilya Ryzhenkov said on July 30, 2004 12:43 AM:
Well, I suppose FCL should not contain NotImplementedException at all, other then exception class definition itself. But it has in 1.1
# flipdoubt said on July 30, 2004 4:20 AM:
When implementing an interface, VS.NET lets you press TAB to stub all the methods and properties required by the interface. Each unimplemented code unit comes with a // TODO task, but I want to add a NotImplementedException right after the TODO. Does anyone know how can I change this template or is it a hardcoded behavior?
# Diego Mijelshon said on July 30, 2004 5:29 AM:
Well, using the callee graph in Reflector shows at least 50 places where NotImplementedException is being used, mostly on System.Net, especially in the WebRequest class

Since the class is abstract, those methods should be abstract too, and the extending class should throw NotSupportedException.
# Ron said on July 30, 2004 6:08 AM:
Seems like this would lead to a few good FxCop rules.
# Brad Abrams said on July 30, 2004 6:27 AM:
A couple of you asked how to get better VS support for this... Here is an idea from the VS guys...

We actually generate the code based off of a snippet (an xml file), so that Eric could change it to always add a TODO comment if he'd like. The file for methods is in drive:\program files\Microsoft Visual Studio 8\VC#\Expansions\1033\Expansions for the Beta and is named MethodStubBody. If Eric adds the TODO comment in the Code section of this then it will always be inserted when method body generation is done for implement interface.
# Jeff Key said on July 30, 2004 9:05 AM:
I saw a live taping of Wait, Wait a couple weeks ago. It's even better in person!
# jaybaz [MS] said on July 30, 2004 9:40 AM:
Brad/Eric/others: Do you think the default method stub we're generating is correct? Or do you wish it had a comment, a different exception, or something else in it?

We expect many users to modify that expansion to suit their coding styles; I'm asking if you think we're selecting the right defaults.
# Matthew Douglass said on July 30, 2004 11:53 PM:
Jay - No exceptions please! I've been using the beta for the past week or so and I'm already being driven up the wall by the NotImplementedExceptions everywhere.

My theory is that you should only autogenerate code that's useful -- and I find that the vast majority of the time I'm going to want to implement that method (especially with event handlers) and so you're generating code that exists solely to get deleted.
# marklio said on July 31, 2004 6:50 AM:
To me, auto-generating NotImplementedException is perfect. 1. It's easy to tell at design time by search (it might be nice to have an automatic Not Implemented list) 2. It's easy to tell at run-time why something didn't work. The argument that the code is generated solely to be deleted is precisely the point of NotImplementedException and is an argument FOR the behavior, not against it. It's not like it's that hard to delete it, in fact you can do it with zero extra clicks by clicking on the beginning of the line so that the entire line is selected and start typing. You could also change the expansion if you don't like it. +1 for good defaults.
# RJ said on July 31, 2004 7:25 PM:
Going back to the logic of it... The difference feels pretty clear to me. "Is" versus "Is Not" going to be implemented. The tricky part, to quote a certain well known person, is what your definition of "is" is.

If you view a shipped product as final, NotImpl should never exist in the release build. But, all too often, we ship works in progress. (btw, "we" is not msft, but the entire industry).
# Eric said on August 1, 2004 2:22 AM:
I used Reflector's callee graph window on NotImplementedException.

These are the bad APIs it came up with for Whidbey :-)

MS.Internal.Xml.FloatingHelper.NextAfter(Double, Double) : Double
MS.Internal.Xml.Query.XmlCompilerEnvironment.AddFunctions(XmlExpression) : Void
MS.Internal.Xml.Query.XmlCompilerEnvironment.AddVariableDeclaration(XmlQualifiedName, XmlSchemaType, XmlExpression) : Void
MS.Internal.Xml.Query.XmlILVisitor.VisitDistinct(QilUnary) : QilNode
MS.Internal.Xml.Query.XmlILVisitor.VisitDistinctByValue(QilLoop) : QilNode
MS.Internal.Xml.Query.XmlILVisitor.VisitStrLike(QilBinary) : QilNode
MS.Internal.Xml.Query.XmlILVisitor.VisitStrSubstring(QilTernary) : QilNode
MS.Internal.Xml.Query.XmlILVisitor.VisitXQueryValidate(QilUnaryType) : QilNode
MS.Internal.Xml.Query.XPath.XPathQilFactory.NYI(String) : QilTuple
MS.Internal.Xml.Query.XQueryCompiler.Compile(TextReader, Evidence, String) : XmlExpression
Reflector.Test.CustomAttributeTest.get_TestProperty() : Int32
System.CodeDom.Compiler.CodeDomProvider.CreateCompilerHelper() : ICodeCompiler
System.CodeDom.Compiler.CodeDomProvider.CreateGeneratorHelper() : ICodeGenerator
System.CodeDom.Compiler.CodeDomProvider.CreateParserHelper() : ICodeParser
System.CodeDom.Compiler.CodeDomProvider.GenerateCodeFromMember(CodeTypeMember, TextWriter, CodeGeneratorOptions) : Void
System.Data.Common.ADP.MethodNotImplemented(String) : NotImplementedException
System.Data.Common.ADP.NotImplemented(String) : NotImplementedException
System.Data.ProviderBase.DbConnectionFactory.BeginCreateConnection(DbConnectionBase, DbConnectionOptions, Object, DbConnectionInternal, AsyncCallback, Object) : IAsyncResult
System.Data.ProviderBase.DbConnectionFactory.EndCreateConnection(IAsyncResult) : DbConnectionInternal
System.Data.ProviderBase.DbConnectionInternal.ChangeDatabase(String) : Void
System.Data.ProviderBase.DbDataReaderBase.FillSchemaTable(DataTable) : Void
System.Data.ProviderBase.DbDataReaderBase.GetDataTypeName(Int32) : String
System.Data.ProviderBase.DbDataReaderBase.GetFieldType(Int32) : Type
System.Data.ProviderBase.DbDataReaderBase.GetName(Int32) : String
System.Data.ProviderBase.DbDataReaderBase.GetValue(Int32) : Object
System.Data.SqlClient.SQL.NotificationEncryptionNotImplemented() : NotImplementedException
System.Data.SqlClient.SqlConnection.System.Data.Sql.ISqlConnection.CreateExecutionContext(SqlDefinition) : ISqlExecutionContext
System.Data.SqlClient.SqlDependency..ctor(SqlCommand, String, SqlNotificationAuthType, SqlNotificationEncryptionType, SqlNotificationTransports, Int32)
System.Drawing.Image..ctor(SerializationInfo, StreamingContext)
System.Drawing.SafeNativeMethods+Gdip.StatusException(Int32) : Exception
System.Drawing.SystemFonts.get_CaptionFont() : Font
System.Drawing.SystemFonts.get_DefaultFont() : Font
System.Drawing.SystemFonts.get_IconTitleFont() : Font
System.Drawing.SystemFonts.get_MenuFont() : Font
System.Drawing.SystemFonts.get_MessageBoxFont() : Font
System.Drawing.SystemFonts.get_SmallCaptionFont() : Font
System.Drawing.SystemFonts.get_StatusFont() : Font
System.IO.FileSystemWatcher+FSWAsyncResult.get_AsyncState() : Object
System.IO.FileSystemWatcher+FSWAsyncResult.get_AsyncWaitHandle() : WaitHandle
System.IO.FileSystemWatcher+FSWAsyncResult.get_CompletedSynchronously() : Boolean
System.IO.FileSystemWatcher+FSWAsyncResult.get_IsCompleted() : Boolean
System.Net.EndPoint.Create(SocketAddress) : EndPoint
System.Net.EndPoint.get_AddressFamily() : AddressFamily
System.Net.EndPoint.Serialize() : SocketAddress
System.Net.ExceptionHelper.get_MethodNotImplementedException() : NotImplementedException
System.Net.ExceptionHelper.get_PropertyNotImplementedException() : NotImplementedException
System.Net.ExceptionHelper.methodNotImplementedException : NotImplementedException
System.Net.ExceptionHelper.MethodNotImplementedException : NotImplementedException
System.Net.ExceptionHelper.propertyNotImplementedException : NotImplementedException
System.Net.ExceptionHelper.PropertyNotImplementedException : NotImplementedException
System.Net.HttpListener+DisconnectAsyncResult.get_AsyncState() : Object
System.Net.HttpListener+DisconnectAsyncResult.get_AsyncWaitHandle() : WaitHandle
System.Net.HttpListener+DisconnectAsyncResult.get_CompletedSynchronously() : Boolean
System.Net.HttpListener+DisconnectAsyncResult.get_IsCompleted() : Boolean
System.Net.Mime.MimeBasePart.BeginSend(BaseWriter, AsyncCallback, Object) : IAsyncResult
System.Net.Mime.MimeBasePart.Send(BaseWriter) : Void
System.Net.SSPIWrapper.EncryptDecrypHelper(OP, SSPIInterface, SafeDeleteContext, SecurityBuffer[], Int32) : Int32
System.Net.WebRequest..ctor(SerializationInfo, StreamingContext)
System.Net.WebRequest.Abort() : Void
System.Net.WebRequest.BeginGetRequestStream(AsyncCallback, Object) : IAsyncResult
System.Net.WebRequest.BeginGetResponse(AsyncCallback, Object) : IAsyncResult
System.Net.WebRequest.EndGetRequestStream(IAsyncResult) : Stream
System.Net.WebRequest.EndGetResponse(IAsyncResult) : WebResponse
System.Net.WebRequest.get_ConnectionGroupName() : String
System.Net.WebRequest.get_ContentLength() : Int64
System.Net.WebRequest.get_ContentType() : String
System.Net.WebRequest.get_Credentials() : ICredentials
System.Net.WebRequest.get_Headers() : WebHeaderCollection
System.Net.WebRequest.get_Method() : String
System.Net.WebRequest.get_PreAuthenticate() : Boolean
System.Net.WebRequest.get_Proxy() : IWebProxy
System.Net.WebRequest.get_RequestUri() : Uri
System.Net.WebRequest.get_Timeout() : Int32
System.Net.WebRequest.get_UseDefaultCredentials() : Boolean
System.Net.WebRequest.GetObjectData(SerializationInfo, StreamingContext) : Void
System.Net.WebRequest.GetRequestStream() : Stream
System.Net.WebRequest.GetResponse() : WebResponse
System.Net.WebRequest.RequestCallback(Object) : Void
System.Net.WebRequest.set_ConnectionGroupName(String) : Void
System.Net.WebRequest.set_ContentLength(Int64) : Void
System.Net.WebRequest.set_ContentType(String) : Void
System.Net.WebRequest.set_Credentials(ICredentials) : Void
System.Net.WebRequest.set_Headers(WebHeaderCollection) : Void
System.Net.WebRequest.set_Method(String) : Void
System.Net.WebRequest.set_PreAuthenticate(Boolean) : Void
System.Net.WebRequest.set_Proxy(IWebProxy) : Void
System.Net.WebRequest.set_Timeout(Int32) : Void
System.Net.WebRequest.set_UseDefaultCredentials(Boolean) : Void
System.Net.WebResponse..ctor(SerializationInfo, StreamingContext)
System.Net.WebResponse.Close() : Void
System.Net.WebResponse.get_ContentLength() : Int64
System.Net.WebResponse.get_ContentType() : String
System.Net.WebResponse.get_Headers() : WebHeaderCollection
System.Net.WebResponse.get_ResponseUri() : Uri
System.Net.WebResponse.GetObjectData(SerializationInfo, StreamingContext) : Void
System.Net.WebResponse.GetResponseStream() : Stream
System.Net.WebResponse.set_ContentLength(Int64) : Void
System.Net.WebResponse.set_ContentType(String) : Void
System.Reflection.Assembly.GetManifestResourceStream(String, StackCrawlMark&, Boolean) : Stream
System.Reflection.Emit.ModuleBuilder.GetMethodTokenNoLock(MethodInfo) : MethodToken
System.Reflection.EventInfo.GetOtherMethods(Boolean) : MethodInfo[]
System.Reflection.FieldInfo.get_OptionalCustomModifiers() : Type[]
System.Reflection.FieldInfo.get_RequiredCustomModifiers() : Type[]
System.Reflection.MemberInfo.get_MetadataToken() : Int32
System.Reflection.MemberInfo.get_Module() : Module
System.Reflection.MethodInfo.get_ReturnParameter() : ParameterInfo
System.Reflection.PropertyInfo.GetConstantValue() : Object
System.Runtime.Remoting.Channels.BaseChannelObjectWithProperties.set_Item(Object, Object) : Void
System.Security.AccessControl.ObjectSecurity.Persist(SafeHandle, AccessControlSections) : Void
System.Security.AccessControl.ObjectSecurity.Persist(String, AccessControlSections) : Void
System.Text.RegularExpressions.RegexCompiler.GenerateOneCode() : Void
System.Text.RegularExpressions.RegexInterpreter.Go() : Void
System.Type.get_GenericParameterAttributes() : GenericParameterAttributes
System.Type.get_StructLayoutAttribute() : StructLayoutAttribute
System.Type.MakeArrayType() : Type
System.Type.MakeArrayType(Int32) : Type
System.Type.MakeByRefType() : Type
System.Type.MakePointerType() : Type
System.Web.Security.AuthorizationStoreRoleProvider.FindUsersInRole(String, String) : String[]
System.Web.SiteMapProvider.AddNode(SiteMapNode, SiteMapNode) : Void
System.Web.SiteMapProvider.RemoveNode(SiteMapNode) : Void
System.Web.UI.WebControls.Menu.set_Enabled(Boolean) : Void
System.Windows.Forms.BindingContext.add_CollectionChanged(CollectionChangeEventHandler) : Void
System.Windows.Forms.DataObject.System.Runtime.InteropServices.ComTypes.IDataObject.SetData(FORMATETC&, STGMEDIUM&, Boolean) : Void
System.Xml.Serialization.XmlSerializer.CreateReader() : XmlSerializationReader
System.Xml.Serialization.XmlSerializer.CreateWriter() : XmlSerializationWriter
System.Xml.Serialization.XmlSerializer.Deserialize(XmlSerializationReader) : Object
System.Xml.Serialization.XmlSerializer.Serialize(Object, XmlSerializationWriter) : Void
System.Xml.XmlBinaryWriter.WriteEntityRef(String) : Void
System.Xml.XmlWellFormedWriter.System.Xml.IXmlNamespaceResolver.get_NameTable() : XmlNameTable
System.Xml.XmlWellFormedWriter.System.Xml.IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope) : IDictionary
System.Xml.Xsl.ContainerAction.Compile(Compiler) : Void
# Ken Brubaker said on August 2, 2004 10:36 AM:
Brad Abrams elucidates the difference between NotSupportedException and NotImplementedException.
# Roy Green said on August 2, 2004 3:39 PM:
Actually that's more of a "Says You" type of question.
# Ken said on August 3, 2004 5:21 AM:
I really hate NotSupportedExceptions - they reek of poorly designed interfaces. Implementing an interface is a contract to satisfy the methods defined by the interface and "not supported" is the class designer thumbing his nose at that contract.

It's probably the biggest reason I dislike Java's collections, though I think they did a better job in terms of heirarchy and naming than the .Net collections (I really want to smack the guy who decided to use "List" to refer to array based sequences). The .Net collections certainly aren't innocent of NotSupported abuses, either.

NotImplemented exceptions are a valuable development-time tool, but as you indicated, they should never see the light of day in production code.
# David M. Kean said on August 9, 2004 10:01 PM:
After what Ron said, I had a crack at implementing a simple rule to check for members that throw a NotImplementException.

The rule inherits off a base class provided at http://managedfromdownunder.blogspot.com/2004/08/hello-world-and-fxcop-rules.html">http://managedfromdownunder.blogspot.com/2004/08/hello-world-and-fxcop-rules.html

public class NotImplementedExceptionShouldNotBeThrown : AusSoftIntrospectionRule
{
public NotImplementedExceptionShouldNotBeThrown() : base("NotImplementedExceptionShouldNotBeThrown")
{
}

public override Problem[] Check(Method method)
{
TypeNodeList nodes = RuleUtilities.UnhandledExceptions(method, 1, UnhandledExceptionSearchScope.Unrestricted);

for (int i = 0; i < nodes.Length; i++)
{
if (nodes[i].GetRuntimeType().IsAssignableFrom(typeof(NotImplementedException)))
{
return Problems.AsArray(GetResolution(method.Name.Name, method.DeclaringType.Name.Name));
}
}

return null;
}

public override ProtectionLevels NestedTypeProtectionLevel
{
get { return ProtectionLevels.All; }
}

public override ProtectionLevels MemberProtectionLevel
{
get { return ProtectionLevels.All; }
}

public override ProtectionLevels TypeProtectionLevel
{
get { return ProtectionLevels.All; }
}
}

It needs a bit of work, but it does the job for now.

I have posted another FxCop rule at my blog and also to post a few more rules over the next few weeks.

http://managedfromdownunder.blogspot.com/
# Web Log di Gianluca Carucci said on August 27, 2004 12:37 PM:
# Managed from down under said on September 19, 2004 8:48 AM:
# Managed from down under said on September 19, 2004 8:55 AM:
# Managed from down under said on September 22, 2004 7:05 AM:
# Managed from down under said on September 22, 2004 8:58 AM:
# Mehran Nikoo's Notes said on October 23, 2007 12:44 PM:

NotImplementedException is raised when the body of a type member has yet to be implemented. In some applications

New Comments to this post are disabled

Search

Go

This Blog

Syndication

Page view tracker