BCLTeam's WebLog
view rss
Introduction to Code Contracts [Melitta Andersen]
11/11/2008 external link
This blog post is to provide a bit more detail about the Code Contracts feature that was recently announced at the PDC and in Justin’s blog entry, and that can be found in the Visual Studio 2010 and .NET Framework 4.0 CTP.  I’ll include some information on what can be found in the CTP, some of the history and design decisions we made while developing the feature, and some places to get more information.  Both of the announcements mentioned above give details about why we added this feature, but I’ll summarize here.  The main point of contracts is to reduce bugs by helping you not write them in the first place, or at least catch them sooner.  Contracts let you express statements about the behavior of your code in a way that is accessible to tools for runtime and static analysis. What’s not in the CTP One thing you should note is that the tools to enable runtime checking and static analysis are not in the CTP.  However, you can still write your contracts now and then use the tools when they become available.  This works because the contracts are conditionally defined.  They’ll only appear in your code when you have the CONTRACTS_FULL symbol defined.  Until the tools are available and runtime checking is enabled, do not define this symbol.  Full contract checking will not work without the tools.  However, you also have the option of getting only preconditions with the CONTRACTS_PRECONDITIONS symbol.  Preconditions happen to be in the correct place in the code, so your program will still run with this symbol defined.  But the runtime checking tool provides many additional benefits, such as contract inheritance, so checking is still not recommended without the tools. What is in the CTP The CTP includes a CodeContracts class in the System.Diagnostics.Contracts namespace that allows you to write contracts in your code.  All contracts are static methods that return void.  They take a Boolean expression which encodes the condition that must be true.  They also have an overload that takes a string parameter as a message for when the contract is false.  Contracts are declarative and come at the beginning of your method.  You can think of them as part of the signature.  Here’s a rundown of what contracts are in the CTP: PreconditionsPreconditions are statements about what must be true at method entry for successful execution of the method.  It’s the responsibility of the caller to make sure these conditions are met.  Often, preconditions are used for parameter validation.  There are 3 possible ways to encode preconditions with code contracts:  CodeContract.RequiresThis method simply states a precondition.  Here’s an example:    CodeContract.Requires(parameter >= 0); CodeContract.RequiresAlwaysThis method is the one exception to the conditional compilation rule.  It is always included, no matter which symbols are defined.  Thus, you can use RequiresAlways for preconditions that you want in your released code.  Here’s an example:    CodeContract.RequiresAlways(parameter >= 0); CodeContract.EndContractBlockThis method name might seem a bit odd to include in the precondition section, so let me explain.  Much code already exists in the world that has some kind of parameter validation in the form of “if [condition] then throw [exception]”, e.g.    if (parameter < 0)        throw new ArgumentOutOfRangeException();We don’t expect everyone to go back and change their existing validation code.  However, we wanted a way to let the tools recognize these legacy contracts.  So we added the CodeContract.EndContractBlock method, which tells the tools that all if-checks of that form before the call can be considered preconditions.    if (parameter < 0)        throw new ArgumentOutOfRangeException();    CodeContract.EndContractBlock();This method is needed only if you have no other contracts in your method, as all CodeContract preconditions and postconditions have this effect. PostconditionsPost conditions are guarantees a method makes about what must be true at the conclusion of a method.  It is the method’s responsibility to live up to those promises.  These are declared at the beginning of a method, just like preconditions.  The tools take care of checking them at the right times.  There are two types of post conditions you can write with the CodeContract class.  CodeContract.EnsuresThis method states conditions that must be true upon successful method exit.  For example, this condition says that when the method exits the value will not be null.    CodeContract.Ensures(SomeSharedState != null); CodeContract.EnsuresOnThrow<TException>This method makes guarantees about exceptional termination from a method.   In general, such guarantees can only be made for very specific exceptions, so letting TException be Exception is not a good idea.  For example, the following condition says that if an IOException escapes this method, the given variable is not null.    CodeContract.EnsuresOnThrow<IOException>(SomeSharedState != null); Special values for postconditionsAs you can imagine, it is often necessary to refer to certain values in postconditions, such as the result of the method, or the value of a variable at method entry.  There are methods in the CodeContract class that allow this; they are valid only in a postcondition.  CodeContract.Result<T>()This method represents the value returned from a method.  The T parameter indicates the return type.  For example, the following condition says that the result of this method is always non-negative.    CodeContract.Ensures(CodeContract.Result<Int32>() >= 0); CodeContract.OldValue<T>(T value)This method represents the value as it was at the start of the method or property.  It captures the pre-call value in a shallow copy.  For example, this condition says that the method increased the value of SomeSharedInt.    CodeContract.Ensures(SomeSharedInt > CodeContract.OldValue(SomeSharedInt)); CodeContract.ValueAtReturn<T>(out T value)This method is just to let you refer to the final value of an out parameter in a postcondition.  Since you write postconditions at the beginning of a method, the compilers would otherwise complain as the parameter hasn’t been assigned yet.  Other by-reference parameters don’t need this method.  Normal parameters don’t need this method because the compiler doesn’t care if it sees references to their values before it sees an assignment to them. Object InvariantsThe last major kind of contract that can be expressed with the CodeContract class is the object invariant.  Object invariants are statements about what must be true at all public method exits for an object.  It is up to the programmer to ensure these invariants are maintained.  Object invariants are contained in a separate method that is marked with the ContractInvariantMethodAttribute.  The name of the method does not matter, but it must be parameter-less and return void.  That method contains some number of calls to the CodeContract.Invariant method.  Here’s an example of an invariant stating that the value in Data is always non-negative.        [ContractInvariantMethod]      void ObjectInvariant() {          CodeContract.Invariant(Data >= 0);      }      CodeContract.Assert and CodeContract.AssumeI’ll briefly touch on the other two types of contracts included in the class.  Assert and Assume, unlike the others, aren’t part of a method’s signature, and unlike the others they don’t come at the beginning of a method.  They’re simply statements about what must be true at a particular point in the code.  There exists many other ways to do this verification, but the main value with these methods is that they can be recognized by the tools.  The difference between Assert and Assume is that an Assume is your way to tell the static checker that instead of trying to prove the expression to be true, it should add the expression to its body of facts for your code. Please note that this is only what is in the CTP.  This is a feature still under development, and things could change before we ship.  In fact, we’re considering a couple of changes.  One is changing the class name from CodeContract to Contract to make contracts more readable.  Another is adding more sophisticated runtime failure behavior that is customizable by applications and hosts. History and Design Decisions The idea for this feature originated with the Spec# project in Microsoft Research.  Spec# has its own programming language, an extension of C#, which includes contracts in the syntax of the language.  We’re working closely with a team from Microsoft Research to bring contracts to the BCL.  One of the main questions we’ve had about the way we are including contracts in the .NET Framework is why we chose to implement them as library calls instead of making them part of “the language.” There are quite a few reasons for this, but one of them is that the CLR is the Common Language Runtime, and we wanted a feature that all of the languages using the .NET Framework could use, not just one of them.  The best way to do this was with library calls.  As far as compilers need to be concerned, these are just static method calls.  Spec# was great because it had contracts integrated into the language, but that only solved the problem for one language.  People have brought up attributes as another way we could have accomplished this.  One argument for that approach is that contracts are declarative, and this would make them look more like part of the method signature instead of the method body.  The problem with this approach is that attributes are very limited in what they can express.  It would be difficult or impossible to use attributes for all of the contracts you can write in code.  If you’re concerned about it because of the aesthetics, you might want to check out Scott Guthrie’s demo of VS2010, which starts about 88 minutes into this PDC2008 Keynote. More Information There are a few places you can go if you’re looking for more information. Microsoft Research’s code contracts website. For discussion of contracts, we’re currently sharing the Pex forum until we get our own.  Please use the Code Contracts Community thread. To provide feedback, you can make comments to this post, send mail via this blog’s contact form, or e-mail codconfb_at_microsoft_dot_com.
What's New in the BCL in .NET 4.0 [Justin Van Patten]
5/11/2008 external link
The Visual Studio 2010 and .NET Framework 4.0 CTP is available for download as of last week.  The CTP contains new functionality throughout the .NET Framework, including several new BCL features and improvements: Code ContractsSystem.Diagnostics.Contracts provides a language-agnostic way to express coding assumptions in .NET programs.  The contracts take the form of pre-conditions, post-conditions, and object invariants.  Contracts act as checked documentation of your external and internal APIs.  The contracts are used to improve testing via runtime checking, enable static contract verification, and documentation generation.  We partnered with Microsoft Research to deliver this feature in .NET 4.0.  More information and tools are available on Microsoft Research’s code contracts website.  There’s also a highly-rated PDC session available online. Parallel ExtensionsWe worked with the Parallel Extensions team to add the Task Parallel Library (TPL), Coordination Data Structures, and Parallel LINQ (PLINQ) to the BCL in .NET 4.0.  This includes an improved ThreadPool scheduling algorithm for tasks, the static Parallel class, concurrent collections in System.Collections.Concurrent, and other coordination data structures such as LazyInit<T>, CountdownEvent, Barrier, SemaphoreSlim, SpinLock, SpinWait, and ManualResetEventSlim. More information is available over at the PFX team’s blog.  Also, check out Daniel Moth’s PDC session on Parallel Programming for Managed Developers with the Next Version of Microsoft Visual Studio. BigIntegerSystem.Numerics.BigInteger is an arbitrary-precision integer data type.  We worked with the Microsoft Solver Foundation team to deliver a highly performant big integer implementation.  BigInteger supports all the standard integer operations, including bit manipulation.  It can be used from any .NET language, and some of the new .NET languages—such as F# and IronPython—have support built-in to the language. Memory Mapped FilesSystem.IO.MemoryMappedFiles exposes the memory mapping functionality provided by Windows as first-class managed APIs.  Memory mapped files can be used to efficiently edit very large files and can also be used to create shared memory for inter-process communication.  Along with this feature, we’re also introducing System.IO.UnmanagedMemoryAccessor, a new class that enables random access to unmanaged memory similar to how UnmanagedMemoryStream enables sequential access to such memory. ResourceManager ImprovementsThe ResourceManager in System.Resources has been improved to respect the user’s preferred UI languages when looking for localized resources, instead of only using the CurrentUICulture’s parent chain.  This means if the user has specified that she prefers French and Spanish, the ResourceManager will look for French and Spanish resources before falling back to the neutral resources.  This change is present in Silverlight 2 as well as .NET 4.0. Compression ImprovementsThe compression algorithms in System.IO.Compression have been improved in .NET 4.0.  DeflateStream and GZipStream no longer inflate already compressed data.  This means that in most cases you’ll see much better compression ratios when using these streams on .NET 4.0.  We’ve also removed the 4 GB size limit, so you can now compress streams over 4 GB in size. String Security ChangesThe default partial matching overloads on System.String (StartsWith, EndsWith, IndexOf, and LastIndexOf) have been changed to be culture-agnostic (ordinal) by default.  In addition, ToUpper and ToLower on System.String and System.Char have been changed to use the invariant culture instead of the current culture.  Although we have guidance and FxCop rules that recommend always using overloads that take a StringComparison parameter, unaware developers often just use the default overloads.  In previous versions of .NET, these default overloads do a culture-sensitive comparison using the current culture.  This can often lead to subtle bugs, most notably security vulnerabilities, when unaware developers use the default overloads to do security-sensitive string comparisons.  This change helps mitigate these vulnerabilities.  The change is present in both Silverlight 2 and .NET 4.0.  Even with these changes, our guidance still stands: whenever an overload exists that takes a StringComparison parameter, use it instead of an overload that does not take this parameter.  It makes your code clearer and easier to maintain.  This is especially important because the default overloads for String.Compare and String.CompareTo will remain culture-sensitive because these methods are most often used when sorting strings to be shown to the user.  We plan to add a compat switch in the beta that will allow an app to specify whether it wants the old behavior. We’re also evaluating a number of potential new features and improvements for .NET 4.0 beta: Variance annotationsThe next versions of C# and VB support safe co- and contra-variance for generic interface and delegate types.  Co-variance means that a generic of a type, e.g. an IEnumerable<String>, can be treated as a generic of any supertype, e.g. an IEnumerable<Object>.  Contra-variance means that a generic of a type, e.g. an Action<Object>, can be treated as a generic of a subtype, e.g. an Action<String>.  In C#, co-variance is annotated with the “out” keyword and contra-variance is annotated with the “in” keyword.  We are annotating several interfaces and delegates in the BCL for variance.  You can learn more about co- and contra-variance in Anders Hejlsberg’s PDC session on The Future of C#. TuplesWe are providing common tuple types in the BCL to facilitate language interoperability and to reduce duplication in the framework.  A tuple is a simple generic data structure that holds an ordered set of items of heterogeneous types.  Tuples are supported natively in languages such as F# and IronPython, but are also easy to use from any .NET language such as C# and VB. SortedSet<T>We plan to add a SortedSet<T> collection along with an ISet<T> interface.  SortedSet<T> uses a self-balancing tree which maintains data in sorted order for performance guarantees with insertion, deletion, and searches.  Both the new SortedSet<T> and the existing HashSet<T> implement ISet<T>. File System Enumeration ImprovementsWe plan to add new file system enumeration APIs to System.IO.Directory and System.IO.DirectoryInfo that return IEnumerable<T>’s instead of arrays.  These new APIs are more efficient than the array-based APIs because they do not need to allocate a (potentially large) array and you can access the first results immediately instead of waiting for the entire enumeration to take place.  We’re also planning to add new convenience APIs for efficiently reading, writing, and appending lines from/to a text file using IEnumerable<String>.  These new APIs are useful in LINQ scenarios where you may want to quickly and efficiently query the contents of a text file and write out the results to a log file without allocating any arrays. There are also a bunch of improvements to the CLR in .NET 4.0.  Here’s a high-level summary: In Process Side-by-Side: support for multiple CLR versions running in the same process. Interop improvements: no PIAs (check out Under the Hood: Advances in the .NET Type System and Managed and Native Code Interoperability: Best Practices) Simplified security model GC improvements (notifications and low-latency background collections) Profiling improvements (ability to attach/detach performance and memory profilers on the server) Debugging enhancements (support for Windows Error Reporting mini-dumps) You can learn more about the next version of the CLR in Joshua Goodman’s PDC session on Microsoft .NET Framework: CLR Futures. Over the next couple of weeks we’ll be posting more about the new functionality that’s available in the CTP.  Do note that we’re working on many other improvements for 4.0 that we’re not quite ready to announce just yet. As always, we’d love to hear what you think of the CTP and announcements so far.
BCL Team at PDC 2008 [Justin Van Patten]
25/10/2008 external link
Melitta, Kim, and I will be at PDC next week, along with several other members of the CLR team.  We’ll mostly be hanging out in the lounges chatting with folks and answering questions.  We’ll also be at the Ask-the-Experts night on Wednesday, so if you’ll be at PDC next week, stop by and say hi!  We love chatting with customers and listening to your feedback and suggestions. This year’s PDC has tons of different sessions on a vast array of .NET technologies including ASP.NET, WCF, WF, ADO.NET, Entity Framework, Data Services, XAML, WPF, Silverlight, and many more.  Here are some that you may find of interest: Microsoft .NET Framework: CLR Futures Research: Contract Checking and Automated Test Generation with Pex Managed and Native Code Interoperability: Best Practices Parallel Programming for Managed Developers with the Next Version of Microsoft Visual Studio Framework Design Guidelines Microsoft .NET Framework: Overview and Applications for Babies Managed Extensibility Framework: Overview Microsoft .NET Framework: Declarative Programming Using XAML The Future of C# Natural Interop with Silverlight, Office, and Python in Microsoft Visual C# and Microsoft Visual Basic Future Directions for Microsoft Visual Basic Deep Dive: Dynamic Languages in Microsoft .NET IronRuby: The Right Language for the Right Job An Introduction to Microsoft F# "Oslo": The Language The first five sessions listed above are the ones most closely related to the BCL and CLR; the first two will specifically touch on some of the features that our team (the BCL team) is delivering in .NET 4.0.  Of course there are plenty of other topics to keep an eye on, such as: parallelism, “Oslo”, Visual Studio, cloud computing, Windows 7, Internet Explorer, SQL Server, etc. Stay tuned to this blog next week for more details on what we’ll be unveiling next week at PDC 2008.
The Compare Contract [Kim Hamilton]
6/10/2008 external link
A breaking change? We recently heard from a customer who observed different sorting behavior in .NET FX 3.5 SP1 compared to 3.5 RTM. The different behavior was demonstrated with the following code. The class StringWrapper provided a custom sort in which nulls (null StringWrapper references) were moved to the end of the array. To achieve this, StringWrapper implemented IComparable<StringWrapper> and in its CompareTo method, nulls were always greater than non-nulls.public class MyClass { public static void Main() { StringWrapper a = new StringWrapper(); a.Value = "a"; StringWrapper b = new StringWrapper(); b.Value = "b"; StringWrapper c = new StringWrapper(); c.Value = "c"; StringWrapper d = null; Console.WriteLine("Sort 1:"); StringWrapper[] src1 = new StringWrapper[] { a, c, d, b }; Array.Sort(src1); PrintStringWrappers(src1); // print elements, method included at end } } public class StringWrapper : IComparable<StringWrapper> { private string _value; public string Value { get { return _value; } set { _value = value; } } // Recall that CompareTo returns: // <0 if this object is less than other // 0 if this object is equal to other // >0 if this object is greater than other public int CompareTo(StringWrapper other) { if (other == null) return -1; // nulls are greater than any non-null return Value.CompareTo(other.Value); } public override string ToString() { return Value; } } This custom comparison apparently worked in .NET FX 3.5 RTM, but not .NET FX 3.5 SP1. 3.5 RTM output:a b c null 3.5 SP1 output:a b null c Did the custom comparer really work? The custom comparer worked in that example, in which only one of the array elements was null. Let’s throw in another null and see what happens:Console.WriteLine("Sort 2:"); StringWrapper[] src2 = new StringWrapper[] { a, d, d, c, b }; Array.Sort(src2); PrintStringWrappers(src2); 3.5 RTM output:a b null null c The problem is in the CompareTo method, but it isn’t obvious. The first line in CompareTo actually violates the IComparable<T>.CompareTo contract that any object compares greater than a null reference.public int CompareTo(StringWrapper other) { if (other == null) return -1; // violates CompareTo contract! return Value.CompareTo(other.Value); } The Compare Contract IComparable<T>.CompareTo has the following requirements (from the MSDN docs) For objects A, B, and C, the following must be true: A.CompareTo(A) is required to return zero. If A.CompareTo(B) returns zero, then B.CompareTo(A) is required to return zero. If A.CompareTo(B) returns zero and B.CompareTo(C) returns zero, then A.CompareTo(C) is required to return zero. If A.CompareTo(B) returns a value other than zero, then B.CompareTo(A) is required to return a value of the opposite sign. If A.CompareTo(B) returns a value x that is not equal to zero, and B.CompareTo(C) returns a value y of the same sign as x, then A.CompareTo(C) is required to return a value of the same sign as x and y. By definition, any object compares greater than a null reference (Nothing in Visual Basic), and two null references compare equal to each other. The requirement that any object compares greater than null is a bit of a footnote at the end, so it makes sense that this may not be well known (we should highlight this more). Still, why did the behavior change? (Gory details and a 3.5 RTM performance bug) The high-level problem is that .NET’s sorting makes assumptions based on the Compare contract, so in some cases sorting will special case null, because it “knows” your comparer will adhere to the contract and return values consistent with that assumption. If you don’t adhere to the contract, you’ll get bitten at some point. The details are messier. Over the years, a variety of changes were made to improve the performance of Sort. There was a brief window (released in 3.5 RTM) where, during QuickSort, the swap and pivot steps were broken, and in intermediate steps, it would actually unsort certain already sorted arrays (the array had to contain  null). The end result would be correct, but because the elements were incorrectly swapped, sorting took much longer than it should. We fixed this bug in SP1, and this fix caused the different behavior between RTM and SP1. Comply with Compare contract The only way to ensure stability across versions is to comply with the Compare contract. Otherwise you fall prey to implementation quirks (or even bugs) in the runtime sort implementation. We’d like to be free to change it between releases, because we’d like to keep improving the performance! Enough preaching, what are my options? The interesting thing is that the StringWrapper implementation gets you mostly there. The apparent goal of the wrapper is to implement a special sort of strings that pushes nulls to the end. You can do what you want if you create a StringWrapper with null values, as follows:public int CompareTo(StringWrapper other) { if (other == null) return 1; if (Value == null && other.Value == null) return 0; if (Value == null) return 1; if (other.Value == null) return -1; return Value.CompareTo(other.Value); } This actually obeys the compare contract and won’t be brittle to changes in our sort implementation. Full Source using System; using System.Collections.Generic; public class MyClass { public static void Main() { StringWrapper a = new StringWrapper(); a.Value = "a"; StringWrapper b = new StringWrapper(); b.Value = "b"; StringWrapper c = new StringWrapper(); c.Value = "c"; StringWrapper d = null; StringWrapper e = new StringWrapper(); e.Value = "e"; StringWrapper f = new StringWrapper(); f.Value = "f"; Console.WriteLine("Sort 1:"); StringWrapper[] src1 = new StringWrapper[] { a, c, d, b }; Array.Sort(src1); PrintStringWrappers(src1); // .NET FX 3.5 RTM output: a b c null // .NET FX 3.5 SP1 output: a b null c Console.WriteLine("-----"); Console.WriteLine("Sort 2:"); StringWrapper[] src2 = new StringWrapper[] { a, d, d, c, b }; Array.Sort(src2); PrintStringWrappers(src2); // .NET FX 3.5 RTM output: a b null null c } private static void PrintStringWrappers(StringWrapper[] swArray) { foreach (StringWrapper sw in swArray) { if (sw == null) Console.WriteLine("null"); else Console.WriteLine(sw); } } } public class StringWrapper : IComparable<StringWrapper> { private string _value; public string Value { get { return _value; } set { _value = value; } } // original CompareTo -- violates Compare contract! public int CompareTo(StringWrapper other) { if (other == null) return -1; return Value.CompareTo(other.Value); } // alternate CompareTo, which obeys Compare contract and moves null Values to the end /* public int CompareTo(StringWrapper other) { if (other == null) return 1; if (Value == null && other.Value == null) return 0; if (Value == null) return 1; if (other.Value == null) return -1; return Value.CompareTo(other.Value); } */ public override string ToString() { return Value; } }
Long Paths in .NET, Part 3 of 3 Redux [Kim Hamilton]
8/7/2008 external link
My original part 3 blog caused confusion, mostly because it didn’t tie together loose ends and explain that an immediate .NET “solution” is at best partial. To minimize confusion and answer questions in the comments, I decided to do a complete overhaul and link to the original (here). Win32 file-naming conventions include the MAX_PATH (260 character) restriction. A subset of Win32 APIs allow you to work around the MAX_PATH restriction by adding the \\?\ prefix. Solutions based on the \\?\ prefix Recall that these are the problems with the \\?\ prefix: Other apps may not support this prefix, and may not be able to use these files Not all Win32 APIs allow this prefix, meaning that the file will not necessarily work with other .NET APIs #2 isn’t obvious to many people so let’s focus on that. .NET dependence on Win32 .NET relies heavily on Win32 and isn’t always able to provide clean workarounds to Win32 restrictions. If we introduce a concept that has partial Win32 support, we either: Open up a new set of potential failures, or Add kludges on top of existing functions to make things work An example of (a) is: you move a file to a location enabled with the \\?\ prefix, and then pass that path to another .NET API, which results in a call to a Win32 API that doesn’t support \\?\. (e.g. LoadLibrary). This sequence of operations would fail. An example of (b) is: we try to make things work for Win32 functions that don’t support \\?\. This would be a major undertaking of rebuilding Win32 functionality or re-building a file system in the .NET layer (for example, we associate with shorter paths that can be accessed). Either approach is extremely risky and error prone, and we don’t see this as an option at the moment. .NET solutions based on \\?\, given Win32 restrictions Currently, .NET doesn’t allow you to use the \\?\ prefix at all. Let’s consider how .NET might enable it: Supported by default: .NET adds the \\?\ prefix behind the scenes Because of limited support of the \\?\ prefix, this will at times force you into awkward coding practices, like having to explicitly check size to make sure the file names are supported by your other apps or other functions. Also, this would be a maintenance burden going forward if Win32 provides a solution that isn’t based around \\?\ Supported on an opt-in basis: callers have to opt in, such as by adding the \\?\ prefix This is just like if we had never blocked out the option from Win32 Because this turns off canonicalization, this would be associated with full trust demand, which seems reasonable for applications that want to use long paths Could add convenience API such as Path.ToLongPath(file), which would add the \\?\ prefix for you, before you pass to System.IO APIs. Other Solutions: Softening Impact We also considered off-by-one attempts to soften the MAX_PATH limit, such as auto-shrinking which is done in the Windows shell. It’s compelling because such a path can be supported by other Win32 APIs and the shell. However, based on feedback, we think this just makes the story more confusing. The lack of consistency makes it useful to only corner-case scenarios, and certainly apps wouldn’t want to depend on it. Proposed “Solution” (Best attempt for now) We won’t be able to provide seamless long path support throughout .NET until something is done on the Win32 side to broaden support of long paths throughout their APIs. As a mitigation to at least provide parity with Win32, we propose to allow use of the \\?\ prefix (described in #2 above) to avoid the MAX_PATH limitation. The caller must explicitly use this prefix, at best aided with a helper API as follows:String longPathEnabledName = Path.ToLongPath(@"C:\veryLongPath...\veryLongName.txt"); FileStream fs = new FileStream(longPathEnabledName); This enables use of long paths throughout the System.IO namespace. Support of long path files outside of System.IO will be limited by support of underlying Win32 APIs. This is not a real solution, but this provides core file (reading, writing, etc) functionality for long path files, which is compelling for certain types of apps. Such apps are best described as closed-system, file reading/writing-focused apps. Ideal Solution Some possibilities include: A Win32 solution, supported throughout Win32 APIs for full parity Going forward, less dependence on Strings as paths. This was touched on in my comments to long paths part 1 and is a very large discussion, for some later time. Navigation Part 1 Part 2 Part 3
P/Invoke Interop Assistant [Justin Van Patten]
24/6/2008 external link
The Interop team recently released a new tool called the P/Invoke Interop Assistant.  This tool automatically generates managed p/invoke declarations (in C# or VB) from native signatures.  It includes a quick look-up for the common Win32 libraries and lets you generate p/invoke declarations for any other native library simply by passing it the native signature.  This makes it a lot easier to do interop correctly, without having to understand all the rules and attributes used when marshalling between unmanaged and managed. Here's a screenshot of the tool in action.  Simply type in the name of a Win32 API, in this case CreateFile, and the tool will generate the correct p/invoke declaration. The tool was first released as part of an MSDN Magazine article on Marshaling between Managed and Unmanaged Code back in January.  Now it's on CodePlex along with the source code.  I highly recommend checking it out.
.NET Framework Developer Documentation Survey [Matthew Connelly]
10/6/2008 external link
Help us improve the developer documentation by taking the Visual Studio and .NET Framework Developer Documentation Survey. This survey will give us a better understanding of the type of applications you are developing, how you use help, and how we can improve it. The survey takes only 10 minutes, and we appreciate your feedback!
Long Paths in .NET, Part 3 of 3 [Kim Hamilton]
10/6/2008 external link
Updated 6/10/08 2:20pm: clarified details of proposed solution Here it is, Part 3 of the long path series, which started over a year ago. I apologize for leaving you hanging; the BCL team has been busy lighting up the web. Because of the delay, I’ll summarize the compatibility concerns as context for the proposed solution. Summary of Compat Concerns Recall from Part 1 that one way to bypass the MAX_PATH limit with Win32 File APIs is to prepend \\?\ to the file name. This allows you to create paths that are only subject to NTFS restrictions, and the length limit is 32K. However, \\?\ has another side-effect -- it bypasses all Win32 file name canonicalization. BCL gets a lot of requests for long path support. Some specifically request that we allow the \\?\ prefix. This brings up the question: is \\?\ requested because it allows longer paths, or do users also want to create paths that don’t conform to Win32 naming conventions? Our investigation indicates that, while there are specialized areas where non-canonical file names are useful, the overwhelming majority of users just want longer paths. Why is this distinction important? If you just want longer paths, you don’t necessarily want the side effect of turning off all Win32 file naming conventions. For example: ‘/’ will no longer be converted to ‘\’ ; instead it’s part of the file name Trailing white spaces will no longer be removed; they’re also part of the file name You can create file names with reserved device names. File names like this are problematic for other apps (independent of the path length: using \\?\ you can create a file name shorter than MAX_PATH that doesn’t adhere to Win32 naming conventions), to the extent that (I expect) a great majority of users will want the framework to enforce canonicalization, at least as the default behavior. Note that the above statements are a commentary on unbridled use of \\?\. The problem could still be resolved as follows: behind the scenes we first canonicalize the path using GetFullPathName (since GetFullPathName isn’t subject to the MAX_PATH restriction) and then prefix\\?\. Perhaps non-canonical names could be allowed on an opt-in basis. Either way, suppose .NET lets you create paths up to 32K in length. Now you have a new problem: you have a file that, most likely, no other app on your system can use. It would have to support the \\?\ syntax. Furthermore, many .NET APIs won’t even be able to work with this file: recall from Part 1 that this syntax only works with the Win32 file-related APIs, but not for general Win32 functions that accept paths (e.g. LoadLibrary). Goals This blog series has focused fairly heavily on nuances of the \\?\ prefix, simply because it’s commonly viewed as the workaround to the MAX_PATH limitation. Let’s switch focus to some reasonable goals in the absence of a unified solution (exposed, for example, by Win32 APIs). Reduce the incidence of hitting path length limit for opening existing files in a compatible way; i.e. the path can only be modified into a form that Win32 APIs accept as legal. For users that need consistent access to long paths, even if that involves bypassing Win32 restrictions, allow access to longer/non-canonical (tbd) file names. Because of the compat concerns with Goal 2, we don’t want users to “accidentally” use this solution. Proposed Solution Fortunately, the Vista shell has provided a precedent of allowing longer path names in a compatible way. It’s called auto-path shrinking and it attempts to squeeze a file name into MAX_PATH by shrinking the long file names into the short name equivalents piecewise behind the scenes. Before describing that, note that the proposed solution is a hybrid approach:  1. Try to squeeze the file name into MAX_PATH characters using auto-path shrinking. Only used for existing files, and paths that don't have the file:///?\ prefix (see below) 2. Allow use of the file:///?\ prefix for creating as well as opening (in general allow this for every operation corresponding to a Win32 file API that supports this). We will not attempt to add the file:///?\ prefix behind the scenes; at most we'll provide a helper to perform such as AddLongPathPrefix. In any case, the user must intentionally request this and not stumble into using file:///?\ by accident. This part is TBD: we think it makes sense to expose as an option whether we should always enforce other Win32 file name restrictions other than length, and enforcing file naming rules would be the default. Let's describe auto-path shrinking a bit more. If you pass in a file name that exceeds MAX_PATH: C:\alongdirectoryname\anotherlongdirectoryname\... It will try to shrink it under the MAX_PATH limit by using the short name equivalents: C:\alongd~1\anothe~1\... This solution may seem odd at first (beyond the ironic spin that we’re coming full circle to short file names). But it’s very compelling for adoption in the framework since paths of this form are acceptable to Win32 API (it’s a valid Win32 file name). Some important clarifications: Note that this solution wouldn’t require you to actually use short file names. When you create a file on an NT-based system, a short name is generated and associated with it*. You would be able to pass “normal” (long file name) file names to .NET APIs, and the short name conversion would happen being the scenes. (Just wanted to make it clear that we’re not reverting to the pre-Windows 95 days.) Right now, you can’t use short names to .NET APIs to get around the MAX_PATH restriction. During canonicalization, we expand short names to long names, and throw a PathTooLongException if the long name exceeds MAX_PATH. * This brings up two questions. One is that users can turn off short file name generation via a registry value. This is discussed below. Also, you’ll notice this solution is NT-focused, but Silverlight can run on Macs. We also intend to handle platform-specific path limits with long path efforts, instead of enforcing Windows MAX_PATH (as we do currently). Analysis Allowing use of file:///?\ will likely require a permission demand greater than FileIOPermission, perhaps even full demand for full trust. However, for many apps that need to work with long paths, this isn't a problem. We should investigate ways to relax this demand for partial trust scenarios like isolated storage. Let’s look at some pros and cons of auto-shrinking: Cons: Doesn't work if user has turned off short file names. (But this is uncommon.) Given that shrinking is happening behind the scenes, it could make path length issues even more confusing to users. \\?\ allows a consistent higher limit of 32K. Examples and explanations are given below. Pros: A path name that can be shrunk into MAX_PATH as above is accepted by any Win32 API (clarification: assuming the name is given to the Win32 API in shrunk form. Win32 APIs do not perform auto-shrinking) This is an appealing "try to make it work" solution (if the user hasn't provided file:///?\). Until there’s a standard solution in the Win32 APIs, it’s better from a maintenance and usability perspective if we’re all using a similar approach. We’re curious to hear your feedback about this approach. Navigation Part 1 Part 2 Part 3
.NET Framework Client Profile [Justin Van Patten]
21/5/2008 external link
Last week Soma and Scott Guthrie announced the availability of Visual Studio 2008 and .NET Framework 3.5 SP1 Beta.  As part of this release, we’re introducing the .NET Framework Client Profile, a smaller .NET Framework redist optimized for .NET client applications.  The new redist weighs in at around 26.5 MB, enabling a smaller, faster, more reliable installation experience for .NET client applications on machines that do not already have the .NET Framework installed. .NET Framework Client Profile Assemblies Here's the list of assemblies that are included in the.NET Framework Client Profile.  Please note that this is actually the list of assemblies that will be included in the RTM release of the Client Profile; the beta version released last week includes some assemblies that will not be included in the RTM release (more details below). BCL, "Core FX," and LINQ CustomMarshalers ISymWrapper mscorlib sysglobl System System.AddIn System.AddIn.Contract System.Configuration System.Configuration.Install System.Core System.Security Visual Basic and Visual C++ Language Support Microsoft.VisualBasic Microsoft.VisualC XML System.Xml System.Xml.Linq Windows Forms Accessibility System.Drawing System.Windows.Forms WPF PresentationCore PresentationFramework PresentationFramework.Aero PresentationFramework.Classic PresentationFramework.Luna PresentationFramework.Royale PresentationUI ReachFramework System.Printing System.Windows.Presentation UIAutomationClient UIAutomationClientsideProviders UIAutomationProvider UIAutomationTypes WindowsBase WindowsFormsIntegration ClickOnce System.Deployment WCF, Web Services, Remoting, and Serialization System.IdentityModel System.Runtime.Remoting System.Runtime.Serialization System.Runtime.Serialization.Formatters.Soap System.ServiceModel System.ServiceModel.Web System.ServiceModel.Install System.Transactions System.Web.Services Data Access System.Data System.Data.SqlXml System.Data.DataSetExtensions System.Data.Services.Client Peer to Peer System.Net Active Directory and Enterprise Services System.DirectoryServices System.EnterpriseServices The following assemblies are included in the beta release of the Client Profile but will be removed in the RTM release: jsc Microsoft.JScript Microsoft.Vsa System.DirectoryServices.Protocols System.Management System.Messaging System.ServiceProcess System.Web System.Web.Extensions System.Web.RegularExpressions We'd love to hear your feedback on the list of assemblies in the Client Profile.  If your client app depends on an assembly that isn't listed above, let us know.  I can't guarantee that we'll add the assembly to the Client Profile for RTM, but we'll certainly consider it.  Keep in mind that the more assemblies we add, the more dependencies we may need to pull in, and the larger the package becomes.  This translates into longer download/install times and less reliable installs.  We're aiming to keep the Client Profile as small as possible while still providing the right amount of functionality to satisfy the needs of most .NET client apps. Targeting the .NET Framework Client Profile using Visual Studio 2008 SP1 Visual Studio 2008 SP1 adds a new feature in the project Properties for targeting the Client Profile. After checking the "Client-only Framework subset" checkbox, Visual Studio will generate a warning if your project references an assembly that is not part of the Client Profile or an assembly that depends on an assembly that is not part of the Client Profile. Things to be Aware ofVisual Studio 2008 SP1 Beta generates a warning when referencing assemblies that *are* in the Client Profile Unfortunately the list of assemblies that Visual Studio 2008 SP1 Beta uses to generate warnings is out of sync with the actual assemblies that are included in the beta release of the Client Profile.  So you may find that Visual Studio will generate warnings when referencing some of the Client Profile assemblies listed above, even though the assemblies are included in the Client Profile. To work around this in Visual Studio 2008 SP1 Beta, you can simply ignore the warnings for any assembly in the list above (your application should still compile). Or, you can manually replace the Client.xml files that Visual Studio uses to target the Client Profile (do this at your own risk).  Here are some replacement Client.xml files that are based on the list of assemblies that will be in the RTM release of the Client Profile. %windir%\Microsoft.NET\Framework\v2.0.50727\SubsetList\Client.xml<?xml version="1.0" encoding="utf-8"?> <FileList Redist="20ClientSubsetList"> <File AssemblyName="Accessibility" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="caspol" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="X86" InGAC="false" /> <File AssemblyName="CustomMarshalers" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="dfsvc" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="InstallUtil" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="X86" InGAC="false" /> <File AssemblyName="ISymWrapper" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="Microsoft.VisualBasic" Version="8.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="Microsoft.VisualC" Version="8.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="mscorlib" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="RegAsm" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="X86" InGAC="false" /> <File AssemblyName="sysglobl" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Configuration" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Configuration.Install" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Data" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="System.Data.SqlXml" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Deployment" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.DirectoryServices" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Drawing" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.EnterpriseServices" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="System.Runtime.Remoting" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Runtime.Serialization.Formatters.Soap" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Security" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Transactions" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="System.Web.Services" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Windows.Forms" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Xml" Version="2.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> </FileList> %programfiles%\Reference Assemblies\Microsoft\Framework\v3.0\SubsetList\Client.xml<?xml version="1.0" encoding="utf-8"?> <FileList Redist="30ClientSubsetList"> <File AssemblyName="PresentationCFFRasterizer" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="PresentationCore" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="PresentationFramework" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="PresentationFramework.Aero" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="PresentationFramework.Classic" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="PresentationFramework.Luna" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="PresentationFramework.Royale" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="PresentationUI" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="ReachFramework" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="ServiceModelReg" Version="3.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.IdentityModel" Version="3.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.Printing" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="X86" InGAC="true" /> <File AssemblyName="System.Runtime.Serialization" Version="3.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.ServiceModel" Version="3.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.ServiceModel.Install" Version="3.0.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="UIAutomationClient" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="UIAutomationClientsideProviders" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="UIAutomationProvider" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="UIAutomationTypes" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="WindowsBase" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="WindowsFormsIntegration" Version="3.0.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> </FileList> %programfiles%\Reference Assemblies\Microsoft\Framework\v3.5\SubsetList\Client.xml<?xml version="1.0" encoding="utf-8"?> <FileList Redist="35ClientSubsetList"> <File AssemblyName="System.Net" Version="3.5.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Net" Version="3.5.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.Core" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.Core" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Data.DataSetExtensions" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.Data.DataSetExtensions" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.AddIn" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.AddIn" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.AddIn.Contract" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.AddIn.Contract" Version="2.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="AddInUtil" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="AddInProcess" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="AddInProcess32" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="X86" InGAC="false" /> <File AssemblyName="System.Xml.Linq" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.Xml.Linq" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.ServiceModel.Web" Version="3.5.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.ServiceModel.Web" Version="3.5.0.0" PublicKeyToken="31bf3856ad364e35" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Windows.Presentation" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Windows.Presentation" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> <File AssemblyName="System.Data.Services.Client" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="true" /> <File AssemblyName="System.Data.Services.Client" Version="3.5.0.0" PublicKeyToken="b77a5c561934e089" Culture="neutral" ProcessorArchitecture="MSIL" InGAC="false" /> </FileList> Regardless of the workaround you choose, you should still test your application on a machine that only has the Client Profile installed to ensure your client app works correctly on the Client Profile.Some APIs that exist in Client Profile assemblies are not supported Some APIs that exist in Client Profile assemblies are not supported because we have chosen not to include the dependencies required for them to function properly.  For RTM, we're planning to release some tools (such as an FxCop rule) to help prevent taking a dependency on these APIs when targeting the Client Profile.  And in future versions of the .NET Framework Client Profile, we may even remove these APIs altogether (possibly by moving them to other assemblies).  But until then, you should be aware of these APIs and be sure not to call them from your client app. The following list of APIs are not supported on the Client Profile (even though they exist and are public).  Note: these may change slightly for RTM. System.dll System.CodeDom.* (all APIs in this namespace) System.CodeDom.Compiler.* (all APIs in this namespace) Microsoft.VisualBasic.VBCodeProvider Microsoft.CSharp.CSharpCodeProvider System.Runtime.Remoting.dll System.Runtime.Remoting.Channels.Http.* (all APIs in this namespace) System.Runtime.Remoting.Services.RemotingService System.ServiceModel.dll System.ServiceModel.Activation.* (all APIs in this namespace) System.ServiceModel.ServiceHost System.IdentityModel.dll System.IdentityModel.Selectors.* (all APIs in this namespace) System.Web.Services.dll System.Web.Services.* (all APIs in this namespace) System.Web.Services.Configuration.* (all APIs in this namespace) System.Web.Services.Diagnostics.* (all APIs in this namespace) System.Web.Services.Discovery.* (all APIs in this namespace) System.Web.Services.Protocols.* (all APIs in this namespace) Again, you should test any code that targets the Client Profile on a machine that only has the Client Profile installed to ensure it works correctly on the Client Profile. Conclusion The .NET Framework Client Profile should help significantly improve the experience of deploying .NET client applications on machines that do not already have the .NET Framework installed.  It has been designed to make it as easy as possible to deploy the smallest set of files necessary to run a typical .NET client application today.  Our hope is that your existing .NET client apps can be easily modified to target the Client Profile to take advantage of the improved deployment experience.  If you're having any trouble targeting the Client Profile, or you feel it is missing a crucial assembly required for client scenarios, please let us know! Update: Troy Martez, a Program Manager on the WPF team, has an excellent blog post Introducing the .NET Framework Client Profile with more info on the Client Profile.
Working with Signed Non-Decimal and Bitwise Values [Ron Petrusha]
9/4/2008 external link
Recently, a number of questions have surfaced about the accuracy of the .NET Framework when working with the binary representation of numbers. (For example, see https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=295117.) The issue surfaces most clearly when we convert the hexadecimal or octal string representation of a numeric value that should be out of range of its target data type to that data type. For example, in the following code we would expect that an OverflowException would be thrown when we increment the upper range of a signed integer value by one, call the Convert.ToString method to convert this integer value to its hexadecimal string representation, and then call the Convert.ToInt32 method to convert the string back to an integer. Here is the C# code:const int HEXADECIMAL = 16; // Increment a number so that it is out of range of the Integer type. long number = (long)int.MaxValue + 1; // Convert the number to its hexadecimal string equivalent. string numericString = Convert.ToString(number, HEXADECIMAL); // Convert the number back to an integer. // We expect that this will throw an OverflowException, but it doesn't. try { int targetNumber = Convert.ToInt32(numericString, HEXADECIMAL); Console.WriteLine("0x is equivalent to .", numericString, targetNumber); } catch (OverflowException) { Console.WriteLine("0x is out of the range of the Int32 data type.", numericString); } And here is the equivalent Visual Basic code:Const HEXADECIMAL As Integer = 16 ' Increment a number so that it is out of range of the Integer type. Dim number As Long = CLng(Integer.MaxValue) + 1 ' Convert the number to its hexadecimal string equivalent. Dim numericString As String = Convert.ToString(number, HEXADECIMAL) ' Convert the number back to an integer. ' We expect that this will throw an OverflowException, but it doesn't. Try Dim targetNumber As Integer = Convert.ToInt32(numericString, HEXADECIMAL) Console.WriteLine("0x is equivalent to .", _ numericString, targetNumber) Catch e As OverflowException Console.WriteLine("0x is out of the range of the Int32 data type.", _ numericString) End Try Instead of the expected OverflowException, this code produces what is apparently an erroneous result:0x80000000 is equivalent to -2147483648 If we look at the binary rather than the decimal and hexadecimal representations of this numeric operation, the source of the problem becomes readily apparent. We began with Int32.MaxValue:Bit #: 3 2 1 10987654321098765432109876543210 01111111111111111111111111111111 For Int32.MaxValue, each bit except the highest order bit of the 32-bit value is set. This represents the maximum value of a signed integer because the single unset bit is the sign bit in position 31. Because this bit is unset, it indicates that the value is positive. We then increment Int32.MaxValue by 1. Note that the variable to which we assign the new value is an Int64; we cannot assign the value to an Int32 without exceeding the bounds of the Int32 data type and causing an OverflowException to be thrown. The new bit pattern of the resulting value is:Bit #: 6 5 4 3 2 1 3210987654321098765432109876543210987654321098765432109876543210 0000000000000000000000000000000010000000000000000000000000000000 So incrementing Int32.MaxValue by one sets bit 31 and clears bits 0 through 30. Bits 32 through 62 remain unset and the sign bit in position 63 is set to 0, which indicates that the resulting value is positive. Because leading zeroes are always dropped from the non-decimal string representations of numeric values, the call to Convert.ToString(value, toBase) produces a binary string whose length is 32:Bit #: 3 2 1 10987654321098765432109876543210 10000000000000000000000000000000 This suggests that the unexpected output produced by our code is the result of two different programming errors. First, we’ve inadvertently allowed the string representation of a 64-bit signed integer value to be interpreted as the string representation of a 32-bit signed integer value.  Second, by ignoring how signed and unsigned integers are represented, we’ve allowed a positive integer to be misinterpreted as a signed negative integer. Let’s look at each of these issues in some detail. Accidental Change of Type Ordinarily, the C# compiler enforces type safety by prohibiting implicit narrowing conversions, and the Visual Basic compiler can be configured to prohibit implicit narrowing conversions by setting Option Strict on. This constraint means that, in order to successfully compile code that performs a narrowing conversion, the developer must explicitly use a C# casting operator or a Visual Basic conversion function. This, of course, requires that the developer be aware of the narrowing conversion. In other words, handling a narrowing conversion is the responsibility of the developer. For example, if the previous code is rewritten so that it does not have to parse the string representation of a numeric value, we must deal with the fact that an Int64 cannot be safely converted to an Int32. The resulting C# code is:// Increment a number so that it is out of range of the Integer type. long number = (long)int.MaxValue + 1; // Convert the number back to an integer. // This will throw an OverflowException if the code is compiled // with the /checked switch. try { int targetNumber = (int)number; Console.WriteLine("Converted to a 32-bit integer.", targetNumber); } catch (OverflowException) { Console.WriteLine(" is out of the range of the Int32 data type.", number); } If Option Strict is set on, the resulting Visual Basic code is:' Increment a number so that it is out of range of the Integer type. Dim number As Long = CLng(Integer.MaxValue) + 1 ' Convert the number back to an integer. ' This will throw an OverflowException. Try Dim targetNumber As Integer = CInt(number) Console.WriteLine("Converted to a 32-bit integer.", targetNumber) Catch e As OverflowException Console.WriteLine(" is out of the range of the Int32 data type.", _ number) End Try Conversions can still produce overflows at run time, but at least the compiler alerts the developer that an overflow is possible and should be handled. However, because our original example converted a numeric value to its string representation and then converted it back to a numeric value, we’ve bypassed the safeguards that the compiler implements to alert us to the possibility of data loss in a narrowing conversion. To put it another way, the developer is solely responsible for ensuring type safety and for handling conversions when converting between numbers and their string representations. Had our code enforced type safety, it would have converted the string representation of Int32.MaxValue + 1 to an Int64 value rather than an Int32 value, as the following C# code shows: const int HEXADECIMAL = 16; // Increment a number so that it is out of range of the Integer type. long number = (long)int.MaxValue + 1; // Convert the number to its hexadecimal string equivalent. string numericString = Convert.ToString(number, HEXADECIMAL); // Convert the number back to a long integer. long targetNumber = Convert.ToInt64(numericString, HEXADECIMAL); Console.WriteLine("0x is equivalent to .", numericString, targetNumber); The equivalent Visual Basic code is:Const HEXADECIMAL As Integer = 16 ' Increment a number so that it is out of range of the Integer type. Dim number As Long = CLng(Integer.MaxValue) + 1 ' Convert the number to its hexadecimal string equivalent. Dim numericString As String = Convert.ToString(number, HEXADECIMAL) ' Convert the number back to a long integer. Dim targetNumber As Long = Convert.ToInt64(numericString, HEXADECIMAL) Console.WriteLine("0x is equivalent to .", _ numericString, targetNumber) Working with Numeric Representations A second serious source of error in our initial example is that we’ve failed to consider numeric representations and their effect on our conversion operation. This is a common source of errors in programs. However, while the compiler provides some safeguards against data loss in narrowing conversions, it provides no safeguards when the developer chooses to work with binary data directly. In these cases, ensuring that the representation of a number is appropriate for the operation being performed is always the responsibility of the developer. This is true whenever the developer works with binary (or octal or hexadecimal) data directly either as a sequence of bits (for example, when the developer performs bitwise operations on two values or as a byte array) or when the developer is working with the non-decimal string representation of a numeric value. Moreover, this is true of any platform and is not limited to Microsoft Windows or the .NET Framework. In particular: When performing bitwise operations, such as a bitwise And, the developer must make sure that both operands share the same binary representation. If they do not, the result of the bitwise operation is invalid. When converting the string representation of a number to its numeric equivalent, the developer must make sure that the numeric string representation is of the type expected by the conversion method or operator. Our initial example produced unexpected results because we passed the string representation of what turned out to be an unsigned 32-bit integer to a conversion method, Convert.ToInt32(value, fromBase), that expected the value parameter to be the string representation of a signed 32-bit integer. Note that the actual result of this conversion depends on the particular magnitude of the 32-bit unsigned integer, as the following table illustrates. Unsigned Integer Range Result 0 - 2,147,483,647 (or Int32.MaxValue) Successful conversion (no loss of data). 2,147,483,648 - 4,294,967,295 (or UInt32.MaxValue) value misinterpreted as a negative number. A clearer illustration of the problems that result from working with binary values that have different numeric representations arises when we perform a bitwise operation on integers with different signs. For example, the Visual Basic codeConsole.WriteLine(16 And -3) produces a rather unexpected result of 16 when run under the common language runtime. This result reflects the fact that the runtime uses two’s complement representation for negative integers and absolute magnitude representation for positive integers. The following example illustrates why the result of this bitwise And operation is 16: 00000000000000000000000000010000 And 11111111111111111111111111111101 00000000000000000000000000010000 Although the .NET Framework uses two’s complement representation for signed integers, one’s complement representation is also in use on some platforms. We can determine the method of representation with the two utility functions shown in the following C# and Visual Basic code:// C# public class BinaryUtil { public static bool IsTwosComplement() { return Convert.ToSByte("FF", 16) == -1; } public static bool IsOnesComplement() { return Convert.ToSByte("FE", 16) == -1; } }' Visual Basic Public Class BinaryUtil Public Shared Function IsTwosComplement() As Boolean Return Convert.ToSByte("FF", 16) = -1 End Function Public Shared Function IsOnesComplement() As Boolean Return Convert.ToSByte("FE", 16) = -1 End Function End Class Performing the And operation with integers that have different signs then requires that we use a common method to represent their values. The most common method is a sign and magnitude representation, which uses a variable to store a number’s absolute value and a separate Boolean variable to store its sign. Using this method of representation, we can define the And operation as follows:// C# public static int PerformBitwiseAnd(int operand1, int operand2) { // Set flag if a parameter is negative. bool sign1 = Math.Sign(operand1) == -1; bool sign2 = Math.Sign(operand2) == -1; // Convert two's complement to its absolute magnitude. if (sign1) operand1 = ~operand1 + 1; if (sign2) operand2 = ~operand2 + 1; if (sign1 & sign2) return -1 * (operand1 & operand2); else return operand1 & operand2; }' Visual Basic Public Function PerformBitwiseAnd(ByVal operand1 As Integer, ByVal operand2 As Integer) As Integer ' Set flag if a parameter is negative. Dim sign1 As Boolean = (Math.Sign(operand1) = -1) Dim sign2 As Boolean = (Math.Sign(operand2) = -1) ' Convert two's complement to its absolute magnitude. If sign1 Then operand1 = (Not operand1) + 1 If sign2 Then operand2 = (Not operand2) + 1 If sign1 And sign2 Then Return -1 * (operand1 And operand2) Else Return operand1 And operand2 End If End Function String Representations, Conversions, and Signs While converting binary values to sign and magnitude representation solves the problem of performing binary operations on non-decimal numbers, it does not address either of the issues raised when converting the string representation of a non-decimal number to a numeric value. When performing such string-to-numeric conversions, the root of the problem lies in the fact that at the time it is created, the string representation of a number is effectively disassociated from its underlying numeric value. This can make it impossible to determine the sign of that numeric string representation when it is converted back to a number. However, we can solve the problem of restoring a non-decimal value from its string representation by defining a structure that includes a field to indicate the sign of the decimal value. For example, the following structure includes a Boolean field, Negative, that is set to true when the numeric value from which a non-decimal string representation is derived is negative. It also includes a Value field that stores the non-decimal string representation of a number.// C# struct NumericString { public bool Negative; public string Value; }' Visual Basic Public Structure NumericString Public Negative As Boolean Public Value As String End Structure Storing a sign flag together with the string representation of a non-decimal number preserves the tight coupling between the string representation of a number and its sign. This in turn allows us to examine its sign field and to make sure that the appropriate conversion or action is taken when the string is converted back to a numeric value. For example, the following code defines a static (or Shared in Visual Basic) method named ConvertToSignedInteger that takes a single parameter (an instance of the NumericString structure defined previously) and returns an integer. The method throws an OverflowException if the string’s numeric value overflows the range of the Int32 data type. It also throws an OverflowException if the NumericString.Negative field is False, indicating that the numeric value is negative, but the sign bit is set in the numeric value represented by the NumericString.Value field. This indicates that the numeric value is positive but that its value lies in the range from Int32.MaxValue + 1 to UInt32.MaxValue, which lies entirely outside the range of the Int32 data type.  // C# class ConversionLibrary { public static int ConvertToSignedInteger(NumericString stringValue) { // Convert the string to an Int32. try { int number = Convert.ToInt32(stringValue.Value, 16); // Throw if sign flag is positive but number is interpreted as negative. if ((! stringValue.Negative) && ((number & 0x80000000) == 0x80000000)) throw new OverflowException(String.Format("0x cannot be converted to an Int32.", stringValue.Value)); else return number; } // Handle legitimate overflow exceptions. catch (OverflowException e) { throw new OverflowException(String.Format("0x cannot be converted to an Int32.", stringValue.Value), e); } } }' Visual Basic Public Class ConversionLibrary Public Shared Function ConvertToSignedInteger(ByVal stringValue As NumericString) As Integer ' Convert the string to an Int32. Try Dim number As Integer = Convert.ToInt32(stringValue.Value, 16) ' Throw if sign flag is positive but number is interpreted as negative. If (Not stringValue.Negative) And ((number And &H80000000) = &H80000000) Then Throw New OverflowException(String.Format("0x cannot be converted to an Int32.", _ stringValue.Value)) Else Return number End If ' Handle legitimate overflow exceptions. Catch e As OverflowException Throw New OverflowException(String.Format("0x cannot be converted to an Int32.", _ stringValue.Value), e) End Try End Function End Class Our initial code example returned an erroneous result when we incremented Int32.MaxValue by 1, converted it to a hexadecimal string, and then converted the string back to an integer value. When we perform the same basic set of operations using the NumericString structure and the ConvertToSignedInteger method, the result is an OverflowException. This is shown in the following code:// C# public class Executable { public static void Main() { // Define a number. Int64 number = (long)Int32.MaxValue + 1; // Define its hexadecimal string representation. NumericString stringValue; stringValue.Value = Convert.ToString(number, 16); stringValue.Negative = (Math.Sign(number) < 0); ShowConversionResult(stringValue); NumericString stringValue2; stringValue2.Value = Convert.ToString(Int32.MaxValue, 16); stringValue2.Negative = Math.Sign(Int32.MaxValue) < 0; ShowConversionResult(stringValue2); NumericString stringValue3; stringValue3.Value = Convert.ToString(-16, 16); stringValue3.Negative = Math.Sign(-16) < 0; ShowConversionResult(stringValue3); } private static void ShowConversionResult(NumericString stringValue) { try { Console.WriteLine(ConversionLibrary.ConvertToSignedInteger(stringValue).ToString("N0")); } catch (OverflowException e) { Console.WriteLine(": ", e.GetType().Name, e.Message); } } }' Visual Basic Module Executable Public Sub Main() ' Define a number. Dim number As Int64 = CLng(Int32.MaxValue) + 1 ' Define its hexadecimal string representation. Dim stringValue As NumericString stringValue.Value = Convert.ToString(number, 16) stringValue.Negative = (Math.Sign(number) < 0) ShowConversionResult(stringValue) Dim stringValue2 As NumericString stringValue2.Value = Convert.ToString(Int32.MaxValue, 16) stringValue2.Negative = Math.Sign(Int32.MaxValue) < 0 ShowConversionResult(stringValue2) Dim stringValue3 As NumericString stringValue3.Value = Convert.ToString(-16, 16) stringValue3.Negative = Math.Sign(-16) < 0 ShowConversionResult(stringValue3) End Sub Private Sub ShowConversionResult(ByVal stringValue As NumericString) Try Console.WriteLine(ConversionLibrary.ConvertToSignedInteger(stringValue).ToString("N0")) Catch e As OverflowException Console.WriteLine(": ", e.GetType().Name, e.Message) End Try End Sub End Module When this code is executed, it displays the following output to the console:OverflowException: 0x80000000 cannot be converted to an Int32. 2,147,483,647 -16
Where did BigInteger go? [Melitta Andersen]
4/1/2008 external link
This has been the subject of several recent feedback e-mails we’ve received.  Moreover, a few recent correspondents were kind enough to point out that not only did we remove it, but we didn’t say anything about it.  I apologize for that.  We weren’t trying to be sneaky about it.  When I made my introductory post there were several comments about BigInteger and I’d mentioned that it would not be included in the release in a reply to one of them.  It was also brought up in a comment on Inbar’s post about the .NET 3.5 Beta release.  With all of the comment activity about it on the blog, I forgot that it hadn’t made it up to a regular post. So why was BigInteger cut?  The basic rationale behind making BigInteger internal was that it just wasn't ready to ship.  We thought our implementation met the needs for a BigInteger type.  But then we had some other teams take a look at it and they pointed out some performance and compatibility issues that we just didn't have time to fix before we shipped. It was a really tough call, but we decided that rather than have people write a bunch of code dependent on a BigInteger class that we wanted to revamp or replace, we would pull it from 3.5 and make sure we resolved the issues before we made it available. There’s not too much I can say about the current status of BigInteger.  We do know that you want it.  Since we didn’t get it into 3.5, we’re looking into how we can get it out there but we don’t yet know when we’ll be able to.  We’re also looking into other possible investments in numerics. That’s the story.  If you have some scenarios or applications you definitely need a BigInteger for, I'd appreciate getting that feedback.  If you’ve already posted comments to this effect on another entry or given me feedback in some other way, there’s no need to repost here.  I’ve looked at what you said.  But I want to make sure the type does what it needs to when we release it, so if you’ve got something new, feel free to share. Thanks,Melitta
Parallel Extensions CTP and the Parallel Computing Developer Center [Judd Hall]
30/11/2007 external link
The CLR Team has been working with the Parallel Computing Platform Team for the past year on some innovative ideas in parallel computing.  Yesterday, the Parallel Computing Platform Team announced the Parallel Computing Developer Center along with their first Community Technology Preview (CTP) of Parallel Extensions to the .NET Framework.  We encourage you to download this early release CTP and provide feedback so that we can grow this technology together.  Parallel Extensions is a managed programming model for data parallelism, task parallelism, and coordination on parallel hardware unified by a common work scheduler.  As such, it makes it easier for you to write programs that scale to take advantage of parallel hardware—providing improved performance as the numbers of cores and processors increase—without having to deal with many of the complexities of today’s concurrent programming models.  It does so via library-based support for introducing concurrency into applications written with any .NET language, including but not limited to C# and Visual Basic. Two major components in Parallel Extensions are the Task Parallel Library (TPL), and Parallel LINQ (PLINQ), a technology extending the Language Integrated Query (LINQ) technology introduced in .NET 3.5.  As such, the CTP requires .NET Framework 3.5. With TPL, you get the concept of Tasks, Futures, and Parallel loops, for starters.  So you can take the following: for (int i = 0; i < 100; i++) {     a[i] = a[i]*a[i]; } And make it scalable across all the processors available: Parallel.For(0, 100, delegate(int i) {     a[i] = a[i]*a[i]; }); Similarly, with PLINQ, you get a query execution engine that accepts any LINQ-to-Objects or LINQ-to-XML query and automatically utilizes multiple processors or cores for execution when they are available.  As such, you can take a simple LINQ query: IEnumerable<T> data = ...; var q = data.Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x)); foreach (var e in q) a(e); And scale it: IEnumerable<T> data = ...; var q = data.AsParallel().Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x)); foreach (var e in q) a(e); And behind it all is a work-stealing task scheduler to reduce thread starvation — and this scheduler interleaves TPL tasks with PLINQ queries on-the-fly. There are limitations of course, mostly related to making sure your parallel operations are independent and the such.  And there are known correctness bugs.  As such, it’s worth checking out the extensive documentation posted on the Parallel Computing Developer Center.  There you will find links to articles and videos, and tons of samples. Links: Parallel Computing Developer Center Parallel Extensions to the .NET Framework CTP download Announcement on Soma’s Weblog
December 2007 Cumulative Time Zone Update is Now Available [Josh Free]
29/11/2007 external link
In case you have not heard, the December 2007 cumulative time zone update for Microsoft Windows operating systems is now available.  The update can be downloaded right now from http://support.microsoft.com/kb/942763; the software update will also be available via Windows Update on an upcoming date.  This update includes everything previously released in the August 2007 cumulative time zone update plus additional time zone changes that were singed in to law after the August 2007 update was created.  This includes updates to existing standard time zones such as Arabic, Australia (Central, Eastern, and Tasmania), Egypt, Israel, and South America (E. South America, Central Brazilian). The most notable change is the inclusion of a new time zone for the capital of the Bolivarian Republic of Venezuela, Caracas: Id Display Name Standard Name Daylight Name DST start DST end Venezuela Standard Time (GMT-04:30) Caracas Venezuela Standard Time Venezuela Daylight Time 12/31/2007 at 24:00 Not applicable The TimeZoneInfo class can use the new time zone by referencing its identification string “Venezuela Standard Time” To date Venezuela has typically observed South America Western Standard Time but is in the process of migrating to the new time zone — adjusting clocks backwards 30 minutes, from UTC -4:00 to UTC -4:30.  According to the latest news reports on the official Venezuelan government news site (see translated page) the start date may or may not be changed again between now and the end of calendar year 2007. Additional Information For the latest information on time zone changes please refer to the Microsoft Daylight Saving Time & Time Zone FAQs Blog, Hot Topics for Daylight Saving Time changes in 2007, and http://www.microsoft.com/time/. Update: Fixed typo in the table.
.NET Framework 3.5 Now Available! [Justin Van Patten]
20/11/2007 external link
.NET Framework 3.5 and Visual Studio 2008 have officially shipped!  Soma has the announcement on his blog and the downloads are available here. There's over 250 new features in .NET 3.5 and Visual Studio 2008.  Here's a list of new BCL features available in .NET 3.5: System.DateTimeOffsetA new date time data structure that can specify an exact point in time relative to the UTC time zone.  DateTimeOffset is made up of a DateTime and offset. It includes most of the functionality of the current DateTime and allows seamless conversion to DateTime.  In addition, SQL Server 2008 adds full support for DateTimeOffset as a new column data type.  DateTimeOffset is the new preferred type to use for most date time scenarios.  For more guidance on when to use DateTime vs. DateTimeOffset refer to my blog post introducing DateTimeOffset. System.TimeZoneInfoComprehensive time zone support.  Previously the .NET Framework only supported conversions between Local and UTC times.  TimeZoneInfo enables enumeration of all the time zones supported by the operating system, conversion of date times from one time zone to another, and serialization of time zones across machines. This support includes cases where the Daylight Saving Time (DST) rules can change from one year to the next, such as the recent 2007 DST change in North America, and will do historically accurate conversions across these changes. Support is also provided for detecting invalid or ambiguous times caused by Daylight Saving Time, and creating custom time zones.  See Kathy's TimeZoneOffset Starter Guide (Note: TimeZoneInfo was previously called TimeZone2).  Also check out Josh Free's blog post on Exploring Windows Time Zones with TimeZoneInfo and Working with Ambiguous and Invalid Points in Time. System.Collections.Generic.HashSet<T>A high-performance set collection.  HashSet is an unordered collection that contains unique elements. In addition to the standard collection operations, HashSet provides standard set operations such as union, intersection, and symmetric difference.  See Kim Hamilton's original blog post introducing HashSet. System.IO.PipesSupport for anonymous and named pipes.  Pipes can be used to achieve inter-process communication (IPC) between any process running on the same machine, or on any other windows machine within a network.  Anyone familiar with streams should be comfortable using these new APIs to achieve IPC.  See my original blog post introducing Pipes. System.Diagnostics.EventSchemaTraceListenerEventSchemaTraceListener is highly tuned for logging performance. Similar to the XMLWriterTraceListender, this trace listener logs XML to disk. In particular, this type logs in the event schema, which is shared by some other new technologies. This tracelistener has performance which is drastically improved over previous logging tracelisteners, especially on machines with multiple processors. Additionally, this is the first trace listener which allows many different disk logging options, such as circular logging across multiple files.  See Inbar Gazit's blog post on EventSchemaTraceListener for more info. System.Diagnostics.EventingBetter integration with Event Tracing for Windows (ETW), including an ETW provider and ETW trace listener APIs. System.Threading.ReaderWriterLockSlimA lightweight reader/writer lock class.  ReaderWriterLockSlim supports basic read and write locks, allowing for better scalability for read-only concurrent worker scenarios. As its name implies, this lock performs anywhere from 2x to 5x better than the existing ReaderWriterLock class, and scales better on multi-processor and multi-core machines. This type also supports upgradeable-read support: if code needs to inspect some state before deciding to acquire the write-lock, upgradeable-reads allow concurrency-safe reading with an optional deadlock-free upgrade to write. Recursion is also disabled by default, helping to write correct code, with an optional recursive mode turned on at lock instantiation time. System.Security.CryptographySupport for the "Suite B" set of cryptographic algorithms, as specified by the National Security Agency (NSA).  Cryptography developers can now use the FIPS-certified implementations of advanced SHA hashing algorithms and AES encryption algorithm in managed code. These classes follow the same familiar patterns as the existing cryptography algorithms, making it easy for developers to use the new classes right away.  Check out Shawn Farkas' blog post on the New Crypto Algorithms in .NET 3.5. System.AddInA new add-in hosting model that makes it easy for managed applications to host add-ins (i.e. plug-ins, add-ons, extensions, etc.) with support for Discovery, Activation, Isolation, Unloadability, Sandboxing, and Lifetime management of add-ins.  This is an exciting new feature that makes it easy to create add-ins for your managed applications without having to deal with all the associated isolation and security plumbing yourself.  The CLR Add-In Team Blog has a lot more information on the new add-in model. Also, be sure to check out Jack Gudenkauf's blog on What's new in the .Net Framework 3.5.  He mentions some additional new CLR features (GC, Security, and ThreadPool) that you may find interesting.
Change in System.ServiceProcess shutdown is coming in 3.5 RTM [Inbar Gazit]
1/11/2007 external link
In all current versions of the Framework we do not close the actual service when we get a shutdown request from the OS. Instead we just call OnShutdown and hope that the user has overridden this method and called Stop() themselves. We found out that many developers didn’t know they had to do that and this is a major issue when shutting down Vista laptops as it can add 10-20 seconds, for each managed service, to the time you have to wait before the machine is turned off. To remedy the situation we decided to make a late-game change to the behavior of System.ServiceProcess.ServiceBase.  After we call OnShutdown we will check to see if the service is in the stopped state or not and if it’s not (meaning the developer did not call Stop() themselves) we will call Stop() on your behalf. This guarantees that the service would be stopped quickly when a shutdown operation is taking place to reduce delay and improve the experience of the customer. This was the recommended way to override OnShutdown before. If you have this code — you don’t have to make any changes. If you don’t have this code, you can pick up 3.5 RTM when it’s available to have this issue fixed. class MyService : System.ServiceProcess.ServiceBase {     protected override void OnShutdown() {         // any shutdown-specific code not included in your OnStop method         this.Stop();     } } We will update the documentation to reflect this. Please let us know if this change affects you in any unintended way.