Changes that might require source code modification
- The compiler now enforces the rule requiring the last clause of a switch statement to end with a break, return, throw, or similar statement. Previously, the compiler enforced this rule for all clauses of a switch statement except the last one, contrary to the language reference.
- It is now illegal to have two method overloads that differ only by having a parameter mode that is ref instead of out.
- The index variable of a foreach statement can no longer be assigned to, as specified in the language reference.
- Setting a property on a non-variable of struct type is now an error, as specified in the language reference. Such a property set would not have a useful effect. Getting a property is still allowed.
- The semantics for determining when static field initializers are run are relaxed. If a static constructor is not present, static field initializers might run earlier than they did before. Use a static constructor to use the old precise semantics.
- Some small holes in unmanaged code are plugged and the syntax of the fixed statement is slightly tightened in some cases.
- Unknown rank arrays (such as int[?]) are no longer supported by the compiler in any way.
- Backtick quoted strings (such as $hello$) are no longer supported. Use @"hello" instead.
- Using unsafe as a statement is no longer supported. Place unsafe as a modifier on the method or property instead.
- A bug was fixed where the compiler was not generating errors for casts of constant values that overflow at compile time. This might require adding the keyword checked in some places.
- Modifiers on property accessors (get or set) are no longer supported. The modifiers (such as virtual) must be placed on the property declaration itself. A tool can help make this change automatically.
- The syntax for events that use a get or set accessor is no longer supported. Code should now use add and remove accessors that contain the code for adding or removing a delegate (implicitly named value) to the list of event sinks.
- A delegate with a pointer parameter must be declared with the unsafe modifier.
- Performing a cast that can never succeed with the as operator now generates an error, just as with the normal cast operator. Previously, this was only a warning.
- The compiler now correctly assumes that a library without a CLSCompliant attribute is non-compliant. Previously, the compiler assumed that a library without the attribute was compliant.
- Arrays of arrays are no longer considered CLS-compliant types.
- Attribute target specifiers have been added. In certain cases, the location of an attribute is insufficient to determine which item the attribute refers to. For example, an attribute immediately before a method might refer to the method or only to the return value of the method. In such a case, C# now allows a target specifier on the attribute that indicates what the attribute is intended for. Without the target specifier, the attribute is assumed to apply to the primary item that follows the attribute. The complete list of target override specifiers is assembly, module, type, method, property, field, param, event, and return. This will require code changes for marshaling attributes applied to the return value of a method. What was previously written as:
[MarshalAs(...)] string testString()
must now be written as:
[return:MarshalAs(...)] string testString()
- Old attribute forms are no longer allowed. C# previously allowed various attributes to be specified that were not actually attribute classes in the base class libraries. These forms are no longer allowed and they must be translated to the actual attribute classes as shown in the following table. (In the table, the final "Attribute" on the class has been omitted, as it would be in C# code).
Previous Form
New Form
attributeusage
System.AttributeUsage
comimport
System.Runtime.InteropServices.ComImport
commethod
No direct mapping. Use System.Runtime.InteropServices.PreserveSig for similar functionality.
conditional
System.Diagnostics.Conditional
dispid
System.Runtime.InteropServices.DispId
dllimport
System.Runtime.InteropServices.DllImport
guid
System.Runtime.InteropServices.Guid
in
System.Runtime.InteropServices.In
interfacetype
System.Runtime.InteropServices.InterfaceType
marshal
System.Runtime.InteropServices.MarshalAs
name
System.Runtime.CompilerServices.CSharp.IndexerName
nativetype
No direct mapping. Use System.Runtime.InteropServices.MarshalAs for similar functionality.
nonserialized
System.NonSerialized
obsolete
System.Obsolete
out
System.Runtime.InteropServices.Out
returnshresult
Nno direct mapping. Use System.Runtime.InteropServices.PreserveSig or the PreserveSig argument on DllImport for similar functionality
serializable
System.Serializable
structlayout
System.Runtime.InteropServices.StructLayout
structoffset
System.Runtime.InteropServices.FieldOffset
sysimport
System.Runtime.InteropServices.DllImport
sysstruct
No direct mapping. Use System.Runtime.InteropServices.StructLayout for similar functionality.
uuid
System.Runtime.InteropServices.Guid
Join the conversation! Your thoughts help the community grow.