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.  😉

Comments (22)

  1. Eric Newton says:

    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.

  2. Well, I suppose FCL should not contain NotImplementedException at all, other then exception class definition itself. But it has in 1.1

  3. flipdoubt says:

    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?

  4. Diego Mijelshon says:

    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.

  5. Ron says:

    Seems like this would lead to a few good FxCop rules.

  6. Brad Abrams says:

    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 filesMicrosoft Visual Studio 8VC#Expansions1033Expansions 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.

  7. Jeff Key says:

    I saw a live taping of Wait, Wait a couple weeks ago. It’s even better in person!

  8. jaybaz [MS] says:

    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.

  9. Matthew Douglass says:

    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.

  10. marklio says:

    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.

  11. RJ says:

    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).

  12. Eric says:

    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

  13. Ken Brubaker says:

    Brad Abrams elucidates the difference between NotSupportedException and NotImplementedException.

  14. Roy Green says:

    Actually that’s more of a "Says You" type of question.

  15. Ken says:

    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.

  16. 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/

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