Core .NET libraries breaking changes in .NET Core 1.0-3.0
The core .NET libraries provide the primitives and other general types used by .NET Core.
The following breaking changes are documented on this page:
.NET Core 3.0
Passing GroupCollection to extension methods taking IEnumerable<T> requires disambiguation
When calling an extension method that takes an IEnumerable<T>
on a GroupCollection, you must disambiguate the type using a cast.
Change description
Starting in .NET Core 3.0, System.Text.RegularExpressions.GroupCollection implements IEnumerable<KeyValuePair<String,Group>>
in addition to the other types it implements, including IEnumerable<Group>
. This results in ambiguity when calling an extension method that takes an IEnumerable<T>. If you call such an extension method on a GroupCollection instance, for example, Enumerable.Count, you'll see the following compiler error:
CS1061: 'GroupCollection' does not contain a definition for 'Count' and no accessible extension method 'Count' accepting a first argument of type 'GroupCollection' could be found (are you missing a using directive or an assembly reference?)
In previous versions of .NET, there was no ambiguity and no compiler error.
Version introduced
3.0
Reason for change
This was an unintentional breaking change. Because it has been like this for some time, we don't plan to revert it. In addition, such a change would itself be breaking.
Recommended action
For GroupCollection instances, disambiguate calls to extension methods that accept an IEnumerable<T>
with a cast.
// Without a cast - causes CS1061.
match.Groups.Count(_ => true)
// With a disambiguating cast.
((IEnumerable<Group>)m.Groups).Count(_ => true);
Category
Core .NET libraries
Affected APIs
Any extension method that accepts an IEnumerable<T> is affected. For example:
- System.Collections.Immutable.ImmutableArray.ToImmutableArray<TSource>(IEnumerable<TSource>)
- System.Collections.Immutable.ImmutableDictionary.ToImmutableDictionary
- System.Collections.Immutable.ImmutableHashSet.ToImmutableHashSet
- System.Collections.Immutable.ImmutableList.ToImmutableList<TSource>(IEnumerable<TSource>)
- System.Collections.Immutable.ImmutableSortedDictionary.ToImmutableSortedDictionary
- System.Collections.Immutable.ImmutableSortedSet.ToImmutableSortedSet
- System.Data.DataTableExtensions.CopyToDataTable
- Most of the
System.Linq.Enumerable
methods, for example, System.Linq.Enumerable.Count - System.Linq.ParallelEnumerable.AsParallel
- System.Linq.Queryable.AsQueryable
APIs that report version now report product and not file version
Many of the APIs that return versions in .NET Core now return the product version rather than the file version.
Change description
In .NET Core 2.2 and previous versions, methods such as Environment.Version, RuntimeInformation.FrameworkDescription, and the file properties dialog for .NET Core assemblies reflect the file version. Starting with .NET Core 3.0, they reflect the product version.
The following figure illustrates the difference in version information for the System.Runtime.dll assembly for .NET Core 2.2 (on the left) and .NET Core 3.0 (on the right) as displayed by the Windows Explorer file properties dialog.
Version introduced
3.0
Recommended action
None. This change should make version detection intuitive rather than obtuse.
Category
Core .NET libraries
Affected APIs
Custom EncoderFallbackBuffer instances cannot fall back recursively
Custom EncoderFallbackBuffer instances cannot fall back recursively. The implementation of EncoderFallbackBuffer.GetNextChar() must result in a character sequence that is convertible to the destination encoding. Otherwise, an exception occurs.
Change description
During a character-to-byte transcoding operation, the runtime detects ill-formed or nonconvertible UTF-16 sequences and provides those characters to the EncoderFallbackBuffer.Fallback method. The Fallback
method determines which characters should be substituted for the original nonconvertible data, and these characters are drained by calling EncoderFallbackBuffer.GetNextChar in a loop.
The runtime then attempts to transcode these substitution characters to the target encoding. If this operation succeeds, the runtime continues transcoding from where it left off in the original input string.
Previously, custom implementations of EncoderFallbackBuffer.GetNextChar() can return character sequences that are not convertible to the destination encoding. If the substituted characters cannot be transcoded to the target encoding, the runtime invokes the EncoderFallbackBuffer.Fallback method once again with the substitution characters, expecting the EncoderFallbackBuffer.GetNextChar() method to return a new substitution sequence. This process continues until the runtime eventually sees a well-formed, convertible substitution, or until a maximum recursion count is reached.
Starting with .NET Core 3.0, custom implementations of EncoderFallbackBuffer.GetNextChar() must return character sequences that are convertible to the destination encoding. If the substituted characters cannot be transcoded to the target encoding, an ArgumentException is thrown. The runtime will no longer make recursive calls into the EncoderFallbackBuffer instance.
This behavior only applies when all three of the following conditions are met:
- The runtime detects an ill-formed UTF-16 sequence or a UTF-16 sequence that cannot be converted to the target encoding.
- A custom EncoderFallback has been specified.
- The custom EncoderFallback attempts to substitute a new ill-formed or nonconvertible UTF-16 sequence.
Version introduced
3.0
Recommended action
Most developers needn't take any action.
If an application uses a custom EncoderFallback and EncoderFallbackBuffer class, ensure the implementation of EncoderFallbackBuffer.Fallback populates the fallback buffer with well-formed UTF-16 data that is directly convertible to the target encoding when the Fallback method is first invoked by the runtime.
Category
Core .NET libraries
Affected APIs
Floating-point formatting and parsing behavior changed
Floating-point parsing and formatting behavior (by the Double and Single types) are now IEEE-compliant. This ensures that the behavior of floating-point types in .NET matches that of other IEEE-compliant languages. For example, double.Parse("SomeLiteral")
should always match what C# produces for double x = SomeLiteral
.
Change description
In .NET Core 2.2 and earlier versions, formatting with Double.ToString and Single.ToString, and parsing with Double.Parse, Double.TryParse, Single.Parse, and Single.TryParse are not IEEE-compliant. As a result, it's impossible to guarantee that a value will roundtrip with any supported standard or custom format string. For some inputs, the attempt to parse a formatted value can fail, and for others, the parsed value doesn't equal the original value.
Starting with .NET Core 3.0, floating-point parsing and formatting operations are IEEE 754-compliant.
The following table shows two code snippets and how the output changes between .NET Core 2.2 and .NET Core 3.1.
Code snippet | Output on .NET Core 2.2 | Output on .NET Core 3.1 |
---|---|---|
Console.WriteLine((-0.0).ToString()); |
0 | -0 |
var value = -3.123456789123456789; Console.WriteLine(value == double.Parse(value.ToString())); |
False |
True |
For more information, see the Floating-point parsing and formatting improvements in .NET Core 3.0 blog post.
Version introduced
3.0
Recommended action
The Potential impact to existing code section of the Floating-point parsing and formatting improvements in .NET Core 3.0 blog post suggests some changes you can make to your code if you want to maintain the previous behavior.
- For some differences in formatting, you can get behavior equivalent to the previous behavior by specifying a different format string.
- For differences in parsing, there's no mechanism to fall back to the previous behavior.
Category
Core .NET libraries
Affected APIs
Floating-point parsing operations no longer fail or throw an OverflowException
The floating-point parsing methods no longer throw an OverflowException or return false
when they parse a string whose numeric value is outside the range of the Single or Double floating-point type.
Change description
In .NET Core 2.2 and earlier versions, the Double.Parse and Single.Parse methods throw an OverflowException for values that outside the range of their respective type. The Double.TryParse and Single.TryParse methods return false
for the string representations of out-of-range numeric values.
Starting with .NET Core 3.0, the Double.Parse, Double.TryParse, Single.Parse, and Single.TryParse methods no longer fail when parsing out-of-range numeric strings. Instead, the Double parsing methods return Double.PositiveInfinity for values that exceed Double.MaxValue, and they return Double.NegativeInfinity for values that are less than Double.MinValue. Similarly, the Single parsing methods return Single.PositiveInfinity for values that exceed Single.MaxValue, and they return Single.NegativeInfinity for values that are less than Single.MinValue.
This change was made for improved IEEE 754:2008 compliance.
Version introduced
3.0
Recommended action
This change can affect your code in either of two ways:
Your code depends on the handler for the OverflowException to execute when an overflow occurs. In this case, you should remove the
catch
statement and place any necessary code in anIf
statement that tests whether Double.IsInfinity or Single.IsInfinity istrue
.Your code assumes that floating-point values are not
Infinity
. In this case, you should add the necessary code to check for floating-point values ofPositiveInfinity
andNegativeInfinity
.
Category
Core .NET libraries
Affected APIs
InvalidAsynchronousStateException moved to another assembly
The InvalidAsynchronousStateException class has been moved.
Change description
In .NET Core 2.2 and earlier versions, the InvalidAsynchronousStateException class is found in the System.ComponentModel.TypeConverter assembly.
Starting with .NET Core 3.0, it is found in the System.ComponentModel.Primitives assembly.
Version introduced
3.0
Recommended action
This change only affects applications that use reflection to load the InvalidAsynchronousStateException by calling a method such as Assembly.GetType or an overload of Activator.CreateInstance that assumes the type is in a particular assembly. If that is the case, update the assembly referenced in the method call to reflect the type's new assembly location.
Category
Core .NET libraries
Affected APIs
None.
Replacing ill-formed UTF-8 byte sequences follows Unicode guidelines
When the UTF8Encoding class encounters an ill-formed UTF-8 byte sequence during a byte-to-character transcoding operation, it replaces that sequence with a '�' (U+FFFD REPLACEMENT CHARACTER) character in the output string. .NET Core 3.0 differs from previous versions of .NET Core and the .NET Framework by following the Unicode best practice for performing this replacement during the transcoding operation.
This is part of a larger effort to improve UTF-8 handling throughout .NET, including by the new System.Text.Unicode.Utf8 and System.Text.Rune types. The UTF8Encoding type was given improved error handling mechanics so that it produces output consistent with the newly introduced types.
Change description
Starting with .NET Core 3.0, when transcoding bytes to characters, the UTF8Encoding class performs character substitution based on Unicode best practices. The substitution mechanism used is described by The Unicode Standard, Version 12.0, Sec. 3.9 (PDF) in the heading titled U+FFFD Substitution of Maximal Subparts.
This behavior only applies when the input byte sequence contains ill-formed UTF-8 data. Additionally, if the UTF8Encoding instance has been constructed with throwOnInvalidBytes: true
, the UTF8Encoding
instance will continue to throw on invalid input rather than perform U+FFFD replacement. For more information about the UTF8Encoding
constructor, see UTF8Encoding(Boolean, Boolean).
The following table illustrates the impact of this change with an invalid 3-byte input:
Ill-formed 3-byte input | Output before .NET Core 3.0 | Output starting with .NET Core 3.0 |
---|---|---|
[ ED A0 90 ] |
[ FFFD FFFD ] (2-character output) |
[ FFFD FFFD FFFD ] (3-character output) |
The 3-char output is the preferred output, according to Table 3-9 of the previously linked Unicode Standard PDF.
Version introduced
3.0
Recommended action
No action is required on the part of the developer.
Category
Core .NET libraries
Affected APIs
TypeDescriptionProviderAttribute moved to another assembly
The TypeDescriptionProviderAttribute class has been moved.
Change description
In .NET Core 2.2 and earlier versions, The TypeDescriptionProviderAttribute class is found in the System.ComponentModel.TypeConverter assembly.
Starting with .NET Core 3.0, it is found in the System.ObjectModel assembly.
Version introduced
3.0
Recommended action
This change only affects applications that use reflection to load the TypeDescriptionProviderAttribute type by calling a method such as Assembly.GetType or an overload of Activator.CreateInstance that assumes the type is in a particular assembly. If that is the case, the assembly referenced in the method call should be updated to reflect the type's new assembly location.
Category
Windows Forms
Affected APIs
None.
ZipArchiveEntry no longer handles archives with inconsistent entry sizes
Zip archives list both compressed size and uncompressed size in the central directory and local header. The entry data itself also indicates its size. In .NET Core 2.2 and earlier versions, these values were never checked for consistency. Starting with .NET Core 3.0, they now are.
Change description
In .NET Core 2.2 and earlier versions, ZipArchiveEntry.Open() succeeds even if the local header disagrees with the central header of the zip file. Data is decompressed until the end of the compressed stream is reached, even if its length exceeds the uncompressed file size listed in the central directory/local header.
Starting with .NET Core 3.0, the ZipArchiveEntry.Open() method checks that local header and central header agree on compressed and uncompressed sizes of an entry. If they do not, the method throws an InvalidDataException if the archive's local header and/or data descriptor list sizes that disagree with the central directory of the zip file. When reading an entry, decompressed data is truncated to the uncompressed file size listed in the header.
This change was made to ensure that a ZipArchiveEntry correctly represents the size of its data and that only that amount of data is read.
Version introduced
3.0
Recommended action
Repackage any zip archive that exhibits these problems.
Category
Core .NET libraries
Affected APIs
- ZipArchiveEntry.Open()
- ZipFileExtensions.ExtractToDirectory
- ZipFileExtensions.ExtractToFile
- ZipFile.ExtractToDirectory
FieldInfo.SetValue throws exception for static, init-only fields
Starting in .NET Core 3.0, an exception is thrown when you attempt to set a value on a static, InitOnly field by calling System.Reflection.FieldInfo.SetValue.
Change description
In .NET Framework and versions of .NET Core prior to 3.0, you could set the value of a static field that's constant after it is initialized (readonly in C#) by calling System.Reflection.FieldInfo.SetValue. However, setting such a field in this way resulted in unpredictable behavior based on the target framework and optimization settings.
In .NET Core 3.0 and later versions, when you call SetValue on a static, InitOnly field, a System.FieldAccessException exception is thrown.
Tip
An InitOnly field is one that can only be set at the time it's declared or in the constructor for the containing class. In other words, it's constant after it is initialized.
Version introduced
3.0
Recommended action
Initialize static, InitOnly fields in a static constructor. This applies to both dynamic and non-dynamic types.
Alternatively, you can remove the FieldAttributes.InitOnly attribute from the field, and then call FieldInfo.SetValue.
Category
Core .NET libraries
Affected APIs
- FieldInfo.SetValue(Object, Object)
- FieldInfo.SetValue(Object, Object, BindingFlags, Binder, CultureInfo)
.NET Core 2.1
Path APIs don't throw an exception for invalid characters
APIs that involve file paths no longer validate path characters or throw an ArgumentException if an invalid character is found.
Change description
In .NET Framework and .NET Core 1.0 - 2.0, the methods listed in the Affected APIs section throw an ArgumentException if the path argument contains an invalid path character. Starting in .NET Core 2.1, these methods no longer check for invalid path characters or throw an exception if an invalid character is found.
Reason for change
Aggressive validation of path characters blocks some cross-platform scenarios. This change was introduced so that .NET does not try to replicate or predict the outcome of operating system API calls. For more information, see the System.IO in .NET Core 2.1 sneak peek blog post.
Version introduced
.NET Core 2.1
Recommended action
If your code relied on these APIs to check for invalid characters, you can add a call to Path.GetInvalidPathChars.
Affected APIs
- System.IO.Directory.CreateDirectory
- System.IO.Directory.Delete
- System.IO.Directory.EnumerateDirectories
- System.IO.Directory.EnumerateFiles
- System.IO.Directory.EnumerateFileSystemEntries
- System.IO.Directory.GetCreationTime(String)
- System.IO.Directory.GetCreationTimeUtc(String)
- System.IO.Directory.GetDirectories
- System.IO.Directory.GetDirectoryRoot(String)
- System.IO.Directory.GetFiles
- System.IO.Directory.GetFileSystemEntries
- System.IO.Directory.GetLastAccessTime(String)
- System.IO.Directory.GetLastAccessTimeUtc(String)
- System.IO.Directory.GetLastWriteTime(String)
- System.IO.Directory.GetLastWriteTimeUtc(String)
- System.IO.Directory.GetParent(String)
- System.IO.Directory.Move(String, String)
- System.IO.Directory.SetCreationTime(String, DateTime)
- System.IO.Directory.SetCreationTimeUtc(String, DateTime)
- System.IO.Directory.SetCurrentDirectory(String)
- System.IO.Directory.SetLastAccessTime(String, DateTime)
- System.IO.Directory.SetLastAccessTimeUtc(String, DateTime)
- System.IO.Directory.SetLastWriteTime(String, DateTime)
- System.IO.Directory.SetLastWriteTimeUtc(String, DateTime)
- System.IO.DirectoryInfo ctor
- System.IO.Directory.GetDirectories
- System.IO.Directory.GetFiles
- System.IO.DirectoryInfo.GetFileSystemInfos
- System.IO.File.AppendAllText
- System.IO.File.AppendAllTextAsync
- System.IO.File.Copy
- System.IO.File.Create
- System.IO.File.CreateText
- System.IO.File.Decrypt
- System.IO.File.Delete
- System.IO.File.Encrypt
- System.IO.File.GetAttributes(String)
- System.IO.File.GetCreationTime(String)
- System.IO.File.GetCreationTimeUtc(String)
- System.IO.File.GetLastAccessTime(String)
- System.IO.File.GetLastAccessTimeUtc(String)
- System.IO.File.GetLastWriteTime(String)
- System.IO.File.GetLastWriteTimeUtc(String)
- System.IO.File.Move
- System.IO.File.Open
- System.IO.File.OpenRead(String)
- System.IO.File.OpenText(String)
- System.IO.File.OpenWrite(String)
- System.IO.File.ReadAllBytes(String)
- System.IO.File.ReadAllBytesAsync(String, CancellationToken)
- System.IO.File.ReadAllLines(String)
- System.IO.File.ReadAllLinesAsync(String, CancellationToken)
- System.IO.File.ReadAllText(String)
- System.IO.File.ReadAllTextAsync(String, CancellationToken)
- System.IO.File.SetAttributes(String, FileAttributes)
- System.IO.File.SetCreationTime(String, DateTime)
- System.IO.File.SetCreationTimeUtc(String, DateTime)
- System.IO.File.SetLastAccessTime(String, DateTime)
- System.IO.File.SetLastAccessTimeUtc(String, DateTime)
- System.IO.File.SetLastWriteTime(String, DateTime)
- System.IO.File.SetLastWriteTimeUtc(String, DateTime)
- System.IO.File.WriteAllBytes(String, Byte[])
- System.IO.File.WriteAllBytesAsync(String, Byte[], CancellationToken)
- System.IO.File.WriteAllLines
- System.IO.File.WriteAllLinesAsync
- System.IO.File.WriteAllText
- System.IO.FileInfo ctor
- System.IO.FileInfo.CopyTo
- System.IO.FileInfo.MoveTo
- System.IO.FileStream ctor
- System.IO.Path.GetFullPath(String)
- System.IO.Path.IsPathRooted(String)
- System.IO.Path.GetPathRoot(String)
- System.IO.Path.ChangeExtension(String, String)
- System.IO.Path.GetDirectoryName(String)
- System.IO.Path.GetExtension(String)
- System.IO.Path.HasExtension(String)
- System.IO.Path.Combine
See also
Private fields added to built-in struct types
Private fields were added to certain struct types in reference assemblies. As a result, in C#, those struct types must always be instantiated by using the new operator or default literal.
Change description
In .NET Core 2.0 and previous versions, some provided struct types, for example, ConsoleKeyInfo, could be instantiated without using the new
operator or default literal in C#. This was because the reference assemblies used by the C# compiler didn't contain the private fields for the structs. All private fields for .NET struct types are added to the reference assemblies starting in .NET Core 2.1.
For example, the following C# code compiles in .NET Core 2.0, but not in .NET Core 2.1:
ConsoleKeyInfo key; // Struct type
if (key.ToString() == "y")
{
Console.WriteLine("Yes!");
}
In .NET Core 2.1, the previous code results in the following compiler error: CS0165 - Use of unassigned local variable 'key'
Version introduced
2.1
Recommended action
Instantiate struct types by using the new
operator or default literal.
For example:
ConsoleKeyInfo key = new ConsoleKeyInfo(); // Struct type.
if (key.ToString() == "y")
Console.WriteLine("Yes!");
ConsoleKeyInfo key = default; // Struct type.
if (key.ToString() == "y")
Console.WriteLine("Yes!");
Category
Core .NET libraries
Affected APIs
- System.ArraySegment<T>.Enumerator
- System.ArraySegment<T>
- System.Boolean
- System.Buffers.MemoryHandle
- System.Buffers.StandardFormat
- System.Byte
- System.Char
- System.Collections.DictionaryEntry
- System.Collections.Generic.Dictionary<TKey,TValue>.Enumerator
- System.Collections.Generic.Dictionary<TKey,TValue>.KeyCollection.Enumerator
- System.Collections.Generic.Dictionary<TKey,TValue>.ValueCollection.Enumerator
- System.Collections.Generic.HashSet<T>.Enumerator
- System.Collections.Generic.KeyValuePair<TKey,TValue>
- System.Collections.Generic.LinkedList<T>.Enumerator
- System.Collections.Generic.List<T>.Enumerator
- System.Collections.Generic.Queue<T>.Enumerator
- System.Collections.Generic.SortedDictionary<TKey,TValue>.Enumerator
- System.Collections.Generic.SortedDictionary<TKey,TValue>.KeyCollection.Enumerator
- System.Collections.Generic.SortedDictionary<TKey,TValue>.ValueCollection.Enumerator
- System.Collections.Generic.SortedSet<T>.Enumerator
- System.Collections.Generic.Stack<T>.Enumerator
- System.Collections.Immutable.ImmutableArray<T>.Enumerator
- System.Collections.Immutable.ImmutableArray<T>
- System.Collections.Immutable.ImmutableDictionary<TKey,TValue>.Enumerator
- System.Collections.Immutable.ImmutableHashSet<T>.Enumerator
- System.Collections.Immutable.ImmutableList<T>.Enumerator
- System.Collections.Immutable.ImmutableQueue<T>.Enumerator
- System.Collections.Immutable.ImmutableSortedDictionary<TKey,TValue>.Enumerator
- System.Collections.Immutable.ImmutableSortedSet<T>.Enumerator
- System.Collections.Immutable.ImmutableStack<T>.Enumerator
- System.Collections.Specialized.BitVector32.Section
- System.Collections.Specialized.BitVector32
- LazyMemberInfo
- System.ComponentModel.Design.Serialization.MemberRelationship
- System.ConsoleKeyInfo
- System.Data.SqlTypes.SqlBinary
- System.Data.SqlTypes.SqlBoolean
- System.Data.SqlTypes.SqlByte
- System.Data.SqlTypes.SqlDateTime
- System.Data.SqlTypes.SqlDecimal
- System.Data.SqlTypes.SqlDouble
- System.Data.SqlTypes.SqlGuid
- System.Data.SqlTypes.SqlInt16
- System.Data.SqlTypes.SqlInt32
- System.Data.SqlTypes.SqlInt64
- System.Data.SqlTypes.SqlMoney
- System.Data.SqlTypes.SqlSingle
- System.Data.SqlTypes.SqlString
- System.DateTime
- System.DateTimeOffset
- System.Decimal
- System.Diagnostics.CounterSample
- System.Diagnostics.SymbolStore.SymbolToken
- System.Diagnostics.Tracing.EventSource.EventData
- System.Diagnostics.Tracing.EventSourceOptions
- System.Double
- System.Drawing.CharacterRange
- System.Drawing.Point
- System.Drawing.PointF
- System.Drawing.Rectangle
- System.Drawing.RectangleF
- System.Drawing.Size
- System.Drawing.SizeF
- System.Guid
- System.HashCode
- System.Int16
- System.Int32
- System.Int64
- System.IntPtr
- System.IO.Pipelines.FlushResult
- System.IO.Pipelines.ReadResult
- System.IO.WaitForChangedResult
- System.Memory<T>
- System.ModuleHandle
- System.Net.Security.SslApplicationProtocol
- System.Net.Sockets.IPPacketInformation
- System.Net.Sockets.SocketInformation
- System.Net.Sockets.UdpReceiveResult
- System.Net.WebSockets.ValueWebSocketReceiveResult
- System.Nullable<T>
- System.Numerics.BigInteger
- System.Numerics.Complex
- System.Numerics.Vector<T>
- System.ReadOnlyMemory<T>
- System.ReadOnlySpan<T>.Enumerator
- System.ReadOnlySpan<T>
- System.Reflection.CustomAttributeNamedArgument
- System.Reflection.CustomAttributeTypedArgument
- System.Reflection.Emit.Label
- System.Reflection.Emit.OpCode
- System.Reflection.Metadata.ArrayShape
- System.Reflection.Metadata.AssemblyDefinition
- System.Reflection.Metadata.AssemblyDefinitionHandle
- System.Reflection.Metadata.AssemblyFile
- System.Reflection.Metadata.AssemblyFileHandle
- System.Reflection.Metadata.AssemblyFileHandleCollection.Enumerator
- System.Reflection.Metadata.AssemblyFileHandleCollection
- System.Reflection.Metadata.AssemblyReference
- System.Reflection.Metadata.AssemblyReferenceHandle
- System.Reflection.Metadata.AssemblyReferenceHandleCollection.Enumerator
- System.Reflection.Metadata.AssemblyReferenceHandleCollection
- System.Reflection.Metadata.Blob
- System.Reflection.Metadata.BlobBuilder.Blobs
- System.Reflection.Metadata.BlobContentId
- System.Reflection.Metadata.BlobHandle
- System.Reflection.Metadata.BlobReader
- System.Reflection.Metadata.BlobWriter
- System.Reflection.Metadata.Constant
- System.Reflection.Metadata.ConstantHandle
- System.Reflection.Metadata.CustomAttribute
- System.Reflection.Metadata.CustomAttributeHandle
- System.Reflection.Metadata.CustomAttributeHandleCollection.Enumerator
- System.Reflection.Metadata.CustomAttributeHandleCollection
- System.Reflection.Metadata.CustomAttributeNamedArgument<TType>
- System.Reflection.Metadata.CustomAttributeTypedArgument<TType>
- System.Reflection.Metadata.CustomAttributeValue<TType>
- System.Reflection.Metadata.CustomDebugInformation
- System.Reflection.Metadata.CustomDebugInformationHandle
- System.Reflection.Metadata.CustomDebugInformationHandleCollection.Enumerator
- System.Reflection.Metadata.CustomDebugInformationHandleCollection
- System.Reflection.Metadata.DeclarativeSecurityAttribute
- System.Reflection.Metadata.DeclarativeSecurityAttributeHandle
- System.Reflection.Metadata.DeclarativeSecurityAttributeHandleCollection.Enumerator
- System.Reflection.Metadata.DeclarativeSecurityAttributeHandleCollection
- System.Reflection.Metadata.Document
- System.Reflection.Metadata.DocumentHandle
- System.Reflection.Metadata.DocumentHandleCollection.Enumerator
- System.Reflection.Metadata.DocumentHandleCollection
- System.Reflection.Metadata.DocumentNameBlobHandle
- System.Reflection.Metadata.Ecma335.ArrayShapeEncoder
- System.Reflection.Metadata.Ecma335.BlobEncoder
- System.Reflection.Metadata.Ecma335.CustomAttributeArrayTypeEncoder
- System.Reflection.Metadata.Ecma335.CustomAttributeElementTypeEncoder
- System.Reflection.Metadata.Ecma335.CustomAttributeNamedArgumentsEncoder
- System.Reflection.Metadata.Ecma335.CustomModifiersEncoder
- System.Reflection.Metadata.Ecma335.EditAndContinueLogEntry
- System.Reflection.Metadata.Ecma335.ExceptionRegionEncoder
- System.Reflection.Metadata.Ecma335.FixedArgumentsEncoder
- System.Reflection.Metadata.Ecma335.GenericTypeArgumentsEncoder
- System.Reflection.Metadata.Ecma335.InstructionEncoder
- System.Reflection.Metadata.Ecma335.LabelHandle
- System.Reflection.Metadata.Ecma335.LiteralEncoder
- System.Reflection.Metadata.Ecma335.LiteralsEncoder
- System.Reflection.Metadata.Ecma335.LocalVariablesEncoder
- System.Reflection.Metadata.Ecma335.LocalVariableTypeEncoder
- System.Reflection.Metadata.Ecma335.MethodBodyStreamEncoder.MethodBody
- System.Reflection.Metadata.Ecma335.MethodBodyStreamEncoder
- System.Reflection.Metadata.Ecma335.MethodSignatureEncoder
- System.Reflection.Metadata.Ecma335.NamedArgumentsEncoder
- System.Reflection.Metadata.Ecma335.NamedArgumentTypeEncoder
- System.Reflection.Metadata.Ecma335.NameEncoder
- System.Reflection.Metadata.Ecma335.ParametersEncoder
- System.Reflection.Metadata.Ecma335.ParameterTypeEncoder
- System.Reflection.Metadata.Ecma335.PermissionSetEncoder
- System.Reflection.Metadata.Ecma335.ReturnTypeEncoder
- System.Reflection.Metadata.Ecma335.ScalarEncoder
- System.Reflection.Metadata.Ecma335.SignatureDecoder<TType,TGenericContext>
- System.Reflection.Metadata.Ecma335.SignatureTypeEncoder
- System.Reflection.Metadata.Ecma335.VectorEncoder
- System.Reflection.Metadata.EntityHandle
- System.Reflection.Metadata.EventAccessors
- System.Reflection.Metadata.EventDefinition
- System.Reflection.Metadata.EventDefinitionHandle
- System.Reflection.Metadata.EventDefinitionHandleCollection.Enumerator
- System.Reflection.Metadata.EventDefinitionHandleCollection
- System.Reflection.Metadata.ExceptionRegion
- System.Reflection.Metadata.ExportedType
- System.Reflection.Metadata.ExportedTypeHandle
- System.Reflection.Metadata.ExportedTypeHandleCollection.Enumerator
- System.Reflection.Metadata.ExportedTypeHandleCollection
- System.Reflection.Metadata.FieldDefinition
- System.Reflection.Metadata.FieldDefinitionHandle
- System.Reflection.Metadata.FieldDefinitionHandleCollection.Enumerator
- System.Reflection.Metadata.FieldDefinitionHandleCollection
- System.Reflection.Metadata.GenericParameter
- System.Reflection.Metadata.GenericParameterConstraint
- System.Reflection.Metadata.GenericParameterConstraintHandle
- System.Reflection.Metadata.GenericParameterConstraintHandleCollection.Enumerator
- System.Reflection.Metadata.GenericParameterConstraintHandleCollection
- System.Reflection.Metadata.GenericParameterHandle
- System.Reflection.Metadata.GenericParameterHandleCollection.Enumerator
- System.Reflection.Metadata.GenericParameterHandleCollection
- System.Reflection.Metadata.GuidHandle
- System.Reflection.Metadata.Handle
- System.Reflection.Metadata.ImportDefinition
- System.Reflection.Metadata.ImportDefinitionCollection.Enumerator
- System.Reflection.Metadata.ImportDefinitionCollection
- System.Reflection.Metadata.ImportScope
- System.Reflection.Metadata.ImportScopeCollection.Enumerator
- System.Reflection.Metadata.ImportScopeCollection
- System.Reflection.Metadata.ImportScopeHandle
- System.Reflection.Metadata.InterfaceImplementation
- System.Reflection.Metadata.InterfaceImplementationHandle
- System.Reflection.Metadata.InterfaceImplementationHandleCollection.Enumerator
- System.Reflection.Metadata.InterfaceImplementationHandleCollection
- System.Reflection.Metadata.LocalConstant
- System.Reflection.Metadata.LocalConstantHandle
- System.Reflection.Metadata.LocalConstantHandleCollection.Enumerator
- System.Reflection.Metadata.LocalConstantHandleCollection
- System.Reflection.Metadata.LocalScope
- System.Reflection.Metadata.LocalScopeHandle
- System.Reflection.Metadata.LocalScopeHandleCollection.ChildrenEnumerator
- System.Reflection.Metadata.LocalScopeHandleCollection.Enumerator
- System.Reflection.Metadata.LocalScopeHandleCollection
- System.Reflection.Metadata.LocalVariable
- System.Reflection.Metadata.LocalVariableHandle
- System.Reflection.Metadata.LocalVariableHandleCollection.Enumerator
- System.Reflection.Metadata.LocalVariableHandleCollection
- System.Reflection.Metadata.ManifestResource
- System.Reflection.Metadata.ManifestResourceHandle
- System.Reflection.Metadata.ManifestResourceHandleCollection.Enumerator
- System.Reflection.Metadata.ManifestResourceHandleCollection
- System.Reflection.Metadata.MemberReference
- System.Reflection.Metadata.MemberReferenceHandle
- System.Reflection.Metadata.MemberReferenceHandleCollection.Enumerator
- System.Reflection.Metadata.MemberReferenceHandleCollection
- System.Reflection.Metadata.MetadataStringComparer
- System.Reflection.Metadata.MethodDebugInformation
- System.Reflection.Metadata.MethodDebugInformationHandle
- System.Reflection.Metadata.MethodDebugInformationHandleCollection.Enumerator
- System.Reflection.Metadata.MethodDebugInformationHandleCollection
- System.Reflection.Metadata.MethodDefinition
- System.Reflection.Metadata.MethodDefinitionHandle
- System.Reflection.Metadata.MethodDefinitionHandleCollection.Enumerator
- System.Reflection.Metadata.MethodDefinitionHandleCollection
- System.Reflection.Metadata.MethodImplementation
- System.Reflection.Metadata.MethodImplementationHandle
- System.Reflection.Metadata.MethodImplementationHandleCollection.Enumerator
- System.Reflection.Metadata.MethodImplementationHandleCollection
- System.Reflection.Metadata.MethodImport
- System.Reflection.Metadata.MethodSignature<TType>
- System.Reflection.Metadata.MethodSpecification
- System.Reflection.Metadata.MethodSpecificationHandle
- System.Reflection.Metadata.ModuleDefinition
- System.Reflection.Metadata.ModuleDefinitionHandle
- System.Reflection.Metadata.ModuleReference
- System.Reflection.Metadata.ModuleReferenceHandle
- System.Reflection.Metadata.NamespaceDefinition
- System.Reflection.Metadata.NamespaceDefinitionHandle
- System.Reflection.Metadata.Parameter
- System.Reflection.Metadata.ParameterHandle
- System.Reflection.Metadata.ParameterHandleCollection.Enumerator
- System.Reflection.Metadata.ParameterHandleCollection
- System.Reflection.Metadata.PropertyAccessors
- System.Reflection.Metadata.PropertyDefinition
- System.Reflection.Metadata.PropertyDefinitionHandle
- System.Reflection.Metadata.PropertyDefinitionHandleCollection.Enumerator
- System.Reflection.Metadata.PropertyDefinitionHandleCollection
- System.Reflection.Metadata.ReservedBlob<THandle>
- System.Reflection.Metadata.SequencePoint
- System.Reflection.Metadata.SequencePointCollection.Enumerator
- System.Reflection.Metadata.SequencePointCollection
- System.Reflection.Metadata.SignatureHeader
- System.Reflection.Metadata.StandaloneSignature
- System.Reflection.Metadata.StandaloneSignatureHandle
- System.Reflection.Metadata.StringHandle
- System.Reflection.Metadata.TypeDefinition
- System.Reflection.Metadata.TypeDefinitionHandle
- System.Reflection.Metadata.TypeDefinitionHandleCollection.Enumerator
- System.Reflection.Metadata.TypeDefinitionHandleCollection
- System.Reflection.Metadata.TypeLayout
- System.Reflection.Metadata.TypeReference
- System.Reflection.Metadata.TypeReferenceHandle
- System.Reflection.Metadata.TypeReferenceHandleCollection.Enumerator
- System.Reflection.Metadata.TypeReferenceHandleCollection
- System.Reflection.Metadata.TypeSpecification
- System.Reflection.Metadata.TypeSpecificationHandle
- System.Reflection.Metadata.UserStringHandle
- System.Reflection.ParameterModifier
- System.Reflection.PortableExecutable.CodeViewDebugDirectoryData
- System.Reflection.PortableExecutable.DebugDirectoryEntry
- System.Reflection.PortableExecutable.PEMemoryBlock
- System.Reflection.PortableExecutable.SectionHeader
- System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult>
- System.Runtime.CompilerServices.AsyncTaskMethodBuilder
- System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<TResult>
- System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder
- System.Runtime.CompilerServices.AsyncVoidMethodBuilder
- System.Runtime.CompilerServices.ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter
- System.Runtime.CompilerServices.ConfiguredTaskAwaitable<TResult>
- System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter
- System.Runtime.CompilerServices.ConfiguredTaskAwaitable
- System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<TResult>
- System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<TResult>.ConfiguredValueTaskAwaiter
- System.Runtime.CompilerServices.TaskAwaiter<TResult>
- System.Runtime.CompilerServices.TaskAwaiter
- System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>
- System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>
- System.Runtime.InteropServices.ArrayWithOffset
- System.Runtime.InteropServices.GCHandle
- System.Runtime.InteropServices.HandleRef
- System.Runtime.InteropServices.OSPlatform
- System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken
- System.Runtime.Serialization.SerializationEntry
- System.Runtime.Serialization.StreamingContext
- System.RuntimeArgumentHandle
- System.RuntimeFieldHandle
- System.RuntimeMethodHandle
- System.RuntimeTypeHandle
- System.SByte
- System.Security.Cryptography.CngProperty
- System.Security.Cryptography.ECCurve
- System.Security.Cryptography.HashAlgorithmName
- System.Security.Cryptography.X509Certificates.X509ChainStatus
- System.Security.Cryptography.Xml.X509IssuerSerial
- System.ServiceProcess.SessionChangeDescription
- System.Single
- System.Span<T>.Enumerator
- System.Span<T>
- System.Threading.AsyncFlowControl
- System.Threading.AsyncLocalValueChangedArgs<T>
- System.Threading.CancellationToken
- System.Threading.CancellationTokenRegistration
- System.Threading.LockCookie
- System.Threading.SpinLock
- System.Threading.SpinWait
- System.Threading.Tasks.Dataflow.DataflowMessageHeader
- System.Threading.Tasks.ParallelLoopResult
- System.Threading.Tasks.ValueTask<TResult>
- System.TimeSpan
- System.TimeZoneInfo.TransitionTime
- System.Transactions.TransactionOptions
- System.TypedReference
- System.TypedReference
- System.UInt16
- System.UInt32
- System.UInt64
- System.UIntPtr
- System.Windows.Forms.ColorDialog.Color
- System.Windows.Media.Animation.KeyTime
- System.Windows.Media.Animation.RepeatBehavior
- System.Xml.Serialization.XmlDeserializationEvents
- Windows.Foundation.Point
- Windows.Foundation.Rect
- Windows.Foundation.Size
- Windows.UI.Color
- Windows.UI.Xaml.Controls.Primitives.GeneratorPosition
- Windows.UI.Xaml.CornerRadius
- Windows.UI.Xaml.Duration
- Windows.UI.Xaml.GridLength
- Windows.UI.Xaml.Media.Matrix
- Windows.UI.Xaml.Media.Media3D.Matrix3D
- Windows.UI.Xaml.Thickness
Change in default value of UseShellExecute
ProcessStartInfo.UseShellExecute has a default value of false
on .NET Core. On .NET Framework, its default value is true
.
Change description
Process.Start lets you launch an application directly, for example, with code such as Process.Start("mspaint.exe")
that launches Paint. It also lets you indirectly launch an associated application if ProcessStartInfo.UseShellExecute is set to true
. On .NET Framework, the default value for ProcessStartInfo.UseShellExecute is true
, meaning that code such as Process.Start("mytextfile.txt")
would launch Notepad, if you've associated .txt files with that editor. To prevent indirectly launching an app on .NET Framework, you must explicitly set ProcessStartInfo.UseShellExecute to false
. On .NET Core, the default value for ProcessStartInfo.UseShellExecute is false
. This means that, by default, associated applications are not launched when you call Process.Start
.
The following properties on System.Diagnostics.ProcessStartInfo are only functional when ProcessStartInfo.UseShellExecute is true
:
- ProcessStartInfo.CreateNoWindow
- ProcessStartInfo.ErrorDialog
- ProcessStartInfo.Verb
- ProcessStartInfo.WindowStyle.
This change was introduced in .NET Core for performance reasons. Typically, Process.Start is used to launch an application directly. Launching an app directly does not need to involve the Windows shell and incur the associated performance cost. To make this default case faster, .NET Core changes the default value of ProcessStartInfo.UseShellExecute to false
. You can opt in to the slower path if you need it.
Version introduced
2.1
Note
In earlier versions of .NET Core, UseShellExecute
was not implemented for Windows.
Recommended action
If your app relies on the old behavior, call Process.Start(ProcessStartInfo) with UseShellExecute set to true
on the ProcessStartInfo object.
Category
Core .NET libraries
Affected APIs
OpenSSL versions on macOS
The .NET Core 3.0 and later runtimes on macOS now prefer OpenSSL 1.1.x versions to OpenSSL 1.0.x versions for the AesCcm, AesGcm, DSAOpenSsl, ECDiffieHellmanOpenSsl, ECDsaOpenSsl, RSAOpenSsl, and SafeEvpPKeyHandle types.
The .NET Core 2.1 runtime now supports OpenSSL 1.1.x versions, but still prefers OpenSSL 1.0.x versions.
Change description
Previously, the .NET Core runtime used OpenSSL 1.0.x versions on macOS for types that interact with OpenSSL. The most recent OpenSSL 1.0.x version, OpenSSL 1.0.2, is now out of support. To keep types that use OpenSSL on supported versions of OpenSSL, the .NET Core 3.0 and later runtimes now use newer versions of OpenSSL on macOS.
With this change, the behavior for the .NET Core runtimes on macOS is as follows:
The .NET Core 3.0 and later version runtimes use OpenSSL 1.1.x, if available, and fall back to OpenSSL 1.0.x only if there's no 1.1.x version available.
For callers that use the OpenSSL interop types with custom P/Invokes, follow the guidance in the SafeEvpPKeyHandle.OpenSslVersion remarks. Your app may crash if you don't check the OpenSslVersion value.
The .NET Core 2.1 runtime uses OpenSSL 1.0.x, if available, and falls back to OpenSSL 1.1.x if there's no 1.0.x version available.
The 2.1 runtime prefers the earlier version of OpenSSL because the SafeEvpPKeyHandle.OpenSslVersion property does not exist in .NET Core 2.1, so the OpenSSL version cannot be reliably determined at run time.
Version introduced
- .NET Core 2.1.16
- .NET Core 3.0.3
- .NET Core 3.1.2
Recommended action
Uninstall OpenSSL version 1.0.2 if it's no longer needed.
Install OpenSSL 1.1.x if you use the AesCcm, AesGcm, DSAOpenSsl, ECDiffieHellmanOpenSsl, ECDsaOpenSsl, RSAOpenSsl, or SafeEvpPKeyHandle types.
If you use the OpenSSL interop types with custom P/Invokes, follow the guidance in the SafeEvpPKeyHandle.OpenSslVersion remarks.
Category
Core .NET libraries
Affected APIs
- System.Security.Cryptography.AesCcm
- System.Security.Cryptography.AesGcm
- System.Security.Cryptography.DSAOpenSsl
- System.Security.Cryptography.ECDiffieHellmanOpenSsl
- System.Security.Cryptography.ECDsaOpenSsl
- System.Security.Cryptography.RSAOpenSsl
- System.Security.Cryptography.SafeEvpPKeyHandle
.NET Core 1.0
UnauthorizedAccessException thrown by FileSystemInfo.Attributes
In .NET Core, an UnauthorizedAccessException is thrown when the caller attempts to set a file attribute value but doesn't have write permission.
Change description
In .NET Framework, an ArgumentException is thrown when the caller attempts to set a file attribute value in FileSystemInfo.Attributes but doesn't have write permission. In .NET Core, an UnauthorizedAccessException is thrown instead. (In .NET Core, an ArgumentException is still thrown if the caller attempts to set an invalid file attribute.)
Version introduced
1.0
Recommended action
Modify any catch
statements to catch an UnauthorizedAccessException instead of, or in addition to, an ArgumentException, as necessary.
Category
Core .NET libraries
Affected APIs
Handling corrupted state exceptions is not supported
Handling corrupted-process-state exceptions in .NET Core is not supported.
Change description
Previously, corrupted-process-state exceptions could be caught and handled by managed code exception handlers, for example, by using a try-catch statement in C#.
Starting in .NET Core 1.0, corrupted-process-state exceptions cannot be handled by managed code. The common language runtime doesn't deliver corrupted-process-state exceptions to managed code.
Version introduced
1.0
Recommended action
Avoid the need to handle corrupted-process-state exceptions by addressing the situations that lead to them instead. If it's absolutely necessary to handle corrupted-process-state exceptions, write the exception handler in C or C++ code.
Category
Core .NET libraries
Affected APIs
- System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute
- legacyCorruptedStateExceptionsPolicy element
UriBuilder properties no longer prepend leading characters
UriBuilder.Fragment no longer prepends a leading #
character and UriBuilder.Query no longer prepends a leading ?
character when one is already present.
Change description
In .NET Framework, the UriBuilder.Fragment and UriBuilder.Query properties always prepend a #
or ?
character, respectively, to the value being stored. This behavior can result in multiple #
or ?
characters in the stored value if the string already contains one of these leading characters. For example, the value of UriBuilder.Fragment might become ##main
.
Starting in .NET Core 1.0, these properties no longer prepend the #
or ?
characters to the stored value if one is already present at the beginning of the string.
Version introduced
1.0
Recommended action
You no longer need to explicitly remove any of these leading characters when setting the property values. This is especially useful when you're appending values, because you no longer have to remove the leading #
or ?
each time you append.
For example, the following code snippet shows the behavior difference between .NET Framework and .NET Core.
var builder = new UriBuilder();
builder.Query = "one=1";
builder.Query += "&two=2";
builder.Query += "&three=3";
builder.Query += "&four=4";
Console.WriteLine(builder.Query);
- In .NET Framework, the output is
????one=1&two=2&three=3&four=4
. - In .NET Core, the output is
?one=1&two=2&three=3&four=4
.
Category
Core .NET libraries
Affected APIs
Process.StartInfo throws InvalidOperationException for processes you didn't start
Reading the Process.StartInfo property for processes that your code didn't start throws an InvalidOperationException.
Change description
In .NET Framework, accessing the Process.StartInfo property for processes that your code didn't start returns a dummy ProcessStartInfo object. The dummy object contains default values for all of its properties except EnvironmentVariables.
Starting in .NET Core 1.0, if you read the Process.StartInfo property for a process that you didn't start (that is, by calling Process.Start), an InvalidOperationException is thrown.
Version introduced
1.0
Recommended action
Do not access the Process.StartInfo property for processes that your code didn't start. For example, don't read this property for processes returned by Process.GetProcesses.
Category
Core .NET libraries