Early warning on obsolete members coming in .NET Framework 2.0 (Whidbey)

We have a very cool report we run every week over the entire .NET Framework that shows which members were obsoleted.  As I was reviewing that list, I thought that this would be great information to get out to customers right away.  After all if you are using V1.0 or V1.1 of the .NET Framework you may not have time to pick up each of our community preview bits and try them out.  By making this kind of information available to you in an easy way, it gives you a chance to get a glimpse at the changes that are coming. 

Keep in mind that these are just obsolete in V2.0, not removed, so you can still use them in 2.0, but you should start making your way off them.  Also, I notice many of them suggest using members that are new in Whidbey (such as SafeHandles), clearly you can’t do anything in your codebase today to make that move. 

And, of course the standard caveats apply: this is pre-release, subject to change, etc, etc.  


I have included just MsCorLib here, assuming folks think it is interesting I will find a way to do the other DLLs as well.   Feedback on the message text is also welcome….




Message: AppDomain.GetCurrentOSThreadID has been deprecated because it does not provide a stable ID when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the Thread object returned from Thread.CurrentThread.



Pack(IOCompletionCallback iocb)

Message: This method is not safe. Use Pack (iocb, userData) instead.

UnsafePack(IOCompletionCallback iocb)

Message: This method is not safe. Use UnsafePack (iocb, userData) instead.

Overlapped(Int32 offsetLo,Int32 offsetHi,Int32 hEvent,IAsyncResult ar)

Message: This constructor is not 64-bit compatible. Use the constructor that takes an IntPtr for the event handle.


Message: This property is not 64-bit compatible. Use EventHandleIntPtr instead.




Message: Thread.Suspend has been deprecated because code that uses it is very deadlock-prone. Synchronization of threads or mutually-exclusive access to protected resources should be accomplished using other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore.


Message: Thread.Resume has been deprecated because code that uses it is very deadlock-prone. Synchronization of threads or mutually-exclusive access to protected resources should be accomplished using other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore.



GetReader(Int32 importer,String filename,String searchPath)

Message: This method is not 64-bit compatible. Use the one on ISymbolBinder2 that takes in IntPtr instead.



LoadWithPartialName(String partialName)

Message: Please use Assembly.Load() instead.

LoadWithPartialName(String partialName,Evidence securityEvidence)

Message: Please use Assembly.Load() instead.



AssemblyFlagsAttribute(UInt32 flags)

Message: This non-typed constructor will be removed.

AssemblyFlagsAttribute(Int32 assemblyFlags)

Message: This non-typed constructor will be removed.


Message: This non-typed accessor will be removed.



GetTypeLibName(UCOMITypeLib pTLB)

Message: Use System.Runtime.InteropServices.Marshal.GetTypeLibName(ITypeLib pTLB) instead.

GetTypeLibGuid(UCOMITypeLib pTLB)

Message: Use System.Runtime.InteropServices.Marshal.GetTypeLibGuid(ITypeLib pTLB) instead.

GetTypeLibLcid(UCOMITypeLib pTLB)

Message: Use System.Runtime.InteropServices.Marshal.GetTypeLibLcid(ITypeLib pTLB) instead.

GetTypeInfoName(UCOMITypeInfo pTI)

Message: Use System.Runtime.InteropServices.Marshal.GetTypeInfoName(ITypeInfo pTLB) instead.


Message: This API did not perform any operation and will be removed in future versions of the CLR.


System.Runtime.InteropServices.BIND_OPTS (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.BIND_OPTS instead.


System.Runtime.InteropServices.UCOMIBindCtx (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IBindCtx instead.


System.Runtime.InteropServices.UCOMIConnectionPointContainer (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IConnectionPointContainer instead.


System.Runtime.InteropServices.UCOMIConnectionPoint (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IConnectionPoint instead.


System.Runtime.InteropServices.UCOMIEnumMoniker (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IEnumMoniker instead.


System.Runtime.InteropServices.CONNECTDATA (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.CONNECTDATA instead.


System.Runtime.InteropServices.UCOMIEnumConnections (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IEnumConnections instead.


System.Runtime.InteropServices.UCOMIEnumConnectionPoints (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints instead.


System.Runtime.InteropServices.UCOMIEnumString (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IEnumString instead.


System.Runtime.InteropServices.UCOMIEnumVARIANT (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IEnumVARIANT instead.


System.Runtime.InteropServices.FILETIME (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.FILETIME instead.


System.Runtime.InteropServices.UCOMIMoniker (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IMoniker instead.


System.Runtime.InteropServices.UCOMIRunningObjectTable (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IRunningObjectTable instead.


System.Runtime.InteropServices.STATSTG (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.STATSTG instead.


System.Runtime.InteropServices.UCOMIStream (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IStream instead.


System.Runtime.InteropServices.DESCKIND (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.DESCKIND instead.


System.Runtime.InteropServices.BINDPTR (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.BINDPTR instead.


System.Runtime.InteropServices.UCOMITypeComp (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.ITypeComp instead.


System.Runtime.InteropServices.TYPEKIND (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.TYPEKIND instead.


System.Runtime.InteropServices.TYPEFLAGS (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.TYPEFLAGS instead.


System.Runtime.InteropServices.IMPLTYPEFLAGS (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS instead.


System.Runtime.InteropServices.TYPEATTR (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.TYPEATTR instead.


System.Runtime.InteropServices.FUNCDESC (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.FUNCDESC instead.


System.Runtime.InteropServices.IDLFLAG (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IDLFLAG instead.


System.Runtime.InteropServices.IDLDESC (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.IDLDESC instead.


System.Runtime.InteropServices.PARAMFLAG (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.PARAMFLAG instead.


System.Runtime.InteropServices.PARAMDESC (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.PARAMDESC instead.


System.Runtime.InteropServices.TYPEDESC (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.TYPEDESC instead.


System.Runtime.InteropServices.ELEMDESC (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.ELEMDESC instead.


System.Runtime.InteropServices.VARDESC (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.VARDESC instead.


System.Runtime.InteropServices.DISPPARAMS (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.DISPPARAMS instead.


System.Runtime.InteropServices.EXCEPINFO (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.EXCEPINFO instead.


System.Runtime.InteropServices.FUNCKIND (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.FUNCKIND instead.


System.Runtime.InteropServices.INVOKEKIND (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.INVOKEKIND instead.


System.Runtime.InteropServices.CALLCONV (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.CALLCONV instead.


System.Runtime.InteropServices.FUNCFLAGS (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.FUNCFLAGS instead.


System.Runtime.InteropServices.VARFLAGS (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.VARFLAGS instead.


System.Runtime.InteropServices.UCOMITypeInfo (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.ITypeInfo instead.


System.Runtime.InteropServices.SYSKIND (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.SYSKIND instead.


System.Runtime.InteropServices.LIBFLAGS (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.LIBFLAGS instead.


System.Runtime.InteropServices.TYPELIBATTR (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.TYPELIBATTR instead.


System.Runtime.InteropServices.UCOMITypeLib (Type Obsoleted)

Message: Use System.Runtime.InteropServices.ComTypes.ITypeLib instead.



FileStream(IntPtr handle,FileAccess access)

Message: Use the FileStream constructor family that takes a SafeFileHandle instead.

FileStream(IntPtr handle,FileAccess access,Boolean ownsHandle)

Message: Use the FileStream constructor family that takes a SafeFileHandle instead. Note SafeFileHandle will allow you to specify whether it owns this handle.

FileStream(IntPtr handle,FileAccess access,Boolean ownsHandle,Int32 bufferSize)

Message: Use the FileStream constructor family that takes a SafeFileHandle instead. Note SafeFileHandle will allow you to specify whether it owns this handle.

FileStream(IntPtr handle,FileAccess access,Boolean ownsHandle,Int32 bufferSize,Boolean isAsync)

Message: Use the FileStream constructor family that takes a SafeFileHandle instead. Note SafeFileHandle will allow you to specify whether it owns this handle.


Message: Please use FileStream’s SafeFileHandle property instead.




Message: Please use IsolatedStorageFileStream’s SafeFileHandle property instead.


System.Configuration.Assemblies.AssemblyHash (Type Obsoleted)

Message: The AssemblyHash class is scheduled to be removed.





Comments (26)

  1. PeteB says:

    If Assembly.LoadWithPartialName is gone, is there any way to load with just a partial name? According to the documentation, Assembly.Load load needs the full name (or ‘long name’, as the docs refer to it), and I can recall needing to use LoadWithPartialName for something quite obscure.

  2. Len Weaver says:

    I haven’t used any of the obsoleted classes/members, so I guess I’m safe. You mentioned that you might be wiling to give us a sneak peek at other assemblies… I’d be very interested to find out what will change in the System.Data namespace. I’ve heard very little about the v2.0 data access story.

  3. Calling abort on an already suspended thread is a good example of a deadlock, but surely there is some loss of functionality by making Thread.Suspend & Thread.Resume obsolete???

  4. GetCurrentThreadId() – Message: AppDomain.GetCurrentOSThreadID has been deprecated because it does ….


    The method in the left column is GetCurrentThreadId, but the message is about a non-existant GetCurrentOSThreadID method being deprecated…

    I think the message implies that we should use Thread.CurrentThread.ThreadId .. Just I typo in the message column I guess.

  5. Kit George [Microsoft] says:

    In response the obsoleting of Thread.Abort/Resume, Jonathan Keljo and Chris Brumme, Manager and Architect for the area, reply:

    We’ve never seen a sound reason for using that functionality. Most of the time, people who use Suspend/Resume are trying to do synchronization, and they get into big trouble with deadlocks.

    Synchronization is better (and more safe) with Monitor/Mutex/Semaphore.

  6. PeterB,

    Assembly.Load works with partial name. Just it won’t try to load random assembly from GAC. That is equivalent of dll hell in Win32. You can read Suzanne’s blog (http://blogs.msdn.com/suzcook) for more information.

  7. Actually, I find it interesting that Java also initially had both Resume and Suspend and went ahead and deprecated both. I just find it interesting that .NET seems to have taken a similar path

  8. Steve Maine says:

    I find it sort of amusing that UnsafePack() has been obsoleted with an error message telling the user that the function is not safe. Seems sort of obvious from the method name…

    So is the new overload of UnsafePack() safe or not?

  9. Suzanne Cook says:

    Regarding LoadWithPartialName():

    You can load with a partial name by calling Assembly.Load(). However, you should design your app in such a way that the full display name is available for this call (see http://blogs.msdn.com/suzcook/archive/2003/05/29/57137.aspx about display names). Otherwise, Load() will not be able to return assemblies in the GAC or in a v2.0 host assembly store. (Besides it just being good practice.)

    To see the reasons why it is important to use Load() instead of LoadWithPartialName(), see http://blogs.msdn.com/suzcook/archive/2003/05/30/57159.aspx . Basically, the use of LWPN() causes a serious side-by-side bug in your code.

  10. Kevin Westhead says:

    I see that the UCOMI* types have changed to ComTypes.I*. Out of curiosity, what are the naming guidelines when importing COM types to be used across different assemblies? Should I always use the same parameter names, etc. as defined in the original COM type even though they may not match the other .NET guidelines? This would explain why there is ComTypes.TYPEFLAGS rather than ComTypes.TypeFlags, however this sort of thing does cause FxCop to complain.

  11. Ken Cowan says:

    If I p/invoke to SuspendThread and ResumeThread, will I get the same behavior as today’s Thread.Suspend and Thread.Resume? In particular, will the GC know that my thread is suspended in both cases, and so permit a collection to happen?

    You need Suspend and Resume to implement the Ada Task package. There are features to enable the Ada programmer to ensure his app doesn’t live lock. Worse, the spec is written as if the OS doesn’t do preemptive multitasking. To get all this right, you need a whole lot of Suspend, Resume, fibers and synchronization objects.

    I do agree that it’s easy to deadlock. An early prototype of our performance profiler would occasionally cause deadlocks, due to the GC suspending threads while we held a critical section. I also agree you should make it as easy as humanly possible for people to write apps that synchronize threads correctly. I disagree with the decision to deprecate it, unless there is a viable alternative for a legitimate need.


  12. Once again it seems to be an issue of backwards compatibility biting…(!) If the "threading concept" could be designed from the ground up here, Suspend and Resume would never have existed…. (I slowly realised that today)

    But since we’ve had it before, to be compatible with many issues, it’s difficult, if not impossible, to totally deprecate the functionality.


  13. secretGeek says:

    Hi Brad — this is an excellent page, but (I have to say this) it falls so very far short!

    First off, developers who simply provide comments like ‘This is obsolete, use such and such method instead,’ should be dragged out into the yard, whipped, flogged and then, well, then the real torture should begin.

    This sort of documentation is too big an issue, to involve just the developers who make the change. If these were only internal APIs, then hell yes, this would be sufficient. But that isn’t the case..

    Each message needs to provide at least the following:

    The URL of a webpage/helpfile that explains:

    * What has become obsolete

    * Why it has become obsolete

    * What you should use instead

    * What advantage the developer will get from using the alternative. (i.e. "What’s in it for me?" — code documentation is a public relations exercise after all)

    * The page should also provide the location of a forum where FAQ relating to this change are stored, and where new questions should be asked.

    The API message should have a concise summary of the above information.

    Yes, I think this is a lot of documentation to insist on, but it would ease the effort of upgrading APIs. And to ease that effort will be a major issue with microsoft in the years to come.

    Microsoft is a grown-up now, and it should behave like one.



    (thanks though — this page really is a very good start!)

  14. [Twenty questions] [Thread.Suspend/Resume)] [Worker thread wrapper class] [Winforms: merge and acceptChanges] dsChanges = dsOriginal.GetChanges(); CallToDBUpdateMethod(dsChanges); dsOriginal.Merge(dsChanges);…