Allow Trailing Comma in Type Implementations #8190
-
When working with multiple TFMs, it's possible that you may want to implement interfaces that are only available from certain TFMs. Here's an extreme example from a library I'm developing that targets net461, netstandard2.1, net6, net7, and net8: /// <summary>
/// Represents a 9-digit United States social security number.
/// </summary>
[PublicAPI]
[DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")]
public readonly struct SocialSecurityNumber
#if NET461_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NET6_0
: IFormattable,
IEquatable<SocialSecurityNumber>
#elif NET7
: IFormattable,
IEquatable<SocialSecurityNumber>,
IEqualityOperators<SocialSecurityNumber, SocialSecurityNumber, bool>
#else // NET8_0_OR_GREATER
: IFormattable,
IEquatable<SocialSecurityNumber>,
IEqualityOperators<SocialSecurityNumber, SocialSecurityNumber, bool>,
IUtf8SpanFormattable,
IUtf8SpanParsable<SocialSecurityNumber>
#endif
{
// Specification omitted
} It would be nice to represent this in an abridged format, such as: /// <summary>
/// Represents a 9-digit United States social security number.
/// </summary>
[PublicAPI]
[DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")]
public readonly struct SocialSecurityNumber
: IFormattable,
IEquatable<SocialSecurityNumber>,
#if NET7_0_OR_GREATER
IEqualityOperators<SocialSecurityNumber, SocialSecurityNumber, bool>,
#endif
#if NET8_0_OR_GREATER
IUtf8SpanFormattable,
IUtf8SpanParsable<SocialSecurityNumber>
#endif
{
// Specification omitted
} This however is currently not possible because C# does not allow trailing commas in the interface implementation list (is there a better name for this?). This leads to needing to re-implement as shown above or do SQL-like commas where the comma lives before the item, assuming style rules don't enforce SA1001. (While I admit this does look nice, providing the option for the trailing comma allows users to keep compliance with coding styles). /// <summary>
/// Represents a 9-digit United States social security number.
/// </summary>
[PublicAPI]
[DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")]
public readonly struct SocialSecurityNumber
#pragma warning disable SA1001 // Commas should not be preceeded by whitespace.
: IFormattable
, IEquatable<SocialSecurityNumber>
#if NET7_0_OR_GREATER
, IEqualityOperators<SocialSecurityNumber, SocialSecurityNumber, bool>
#endif
#if NET8_0_OR_GREATER
, IUtf8SpanFormattable
, IUtf8SpanParsable<SocialSecurityNumber>
#endif |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 1 reply
-
In that specific case you could put Allowing trailing commas everywhere would be nice, but it might cause parsing ambiguities. Also, personally, I'd want the language design team to work on something else. |
Beta Was this translation helpful? Give feedback.
-
It would be interesting if |
Beta Was this translation helpful? Give feedback.
-
We have a general issue tracking trailing commas: #391 This should be rolled into that. |
Beta Was this translation helpful? Give feedback.
-
.. and until trailing commas are allowed, you can avoid the problem (and improve readability) by using Link SharpLab #define NET6_0
#define NET7
#define NET8_0_OR_GREATER
using System;
#if NET461_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NET6_0
public readonly partial struct SSN {
readonly int N;
public SSN (int n) => N = n;
}
partial struct SSN : IEquatable<SSN> {
bool IEquatable<SSN>.Equals (SSN ssn) => N == ssn.N;
public override bool Equals (object? obj) => obj is SSN ssn && Equals (ssn);
public static bool operator == (SSN a, SSN b) => a.N == b.N;
public static bool operator != (SSN a, SSN b) => a.N != b.N;
public override int GetHashCode () => N.GetHashCode ();
}
partial struct SSN : IFormattable {
string IFormattable.ToString (string? fmt, IFormatProvider? ifp) => N.ToString (fmt, ifp);
}
#endif
#if NET7
partial struct SSN : System.Numerics.IEqualityOperators<SSN, SSN, bool> {
// public static bool operator == (SSN a, SSN b) => a.N == b.N;
// public static bool operator != (SSN a, SSN b) => a.N != b.N;
}
#endif
#if NET8_0_OR_GREATER
partial struct SSN : IUtf8SpanFormattable {
bool IUtf8SpanFormattable.TryFormat (Span<byte> spn, out int w, ReadOnlySpan<char> fmt, IFormatProvider? ifp)
=> N.TryFormat (spn, out w, fmt, ifp);
}
partial struct SSN : IUtf8SpanParsable<SSN> {
static SSN IUtf8SpanParsable<SSN>.Parse (ReadOnlySpan<byte> spn, IFormatProvider? ifp) => new SSN (int.Parse (spn, ifp));
static bool IUtf8SpanParsable<SSN>.TryParse (ReadOnlySpan<byte> spn, IFormatProvider? ifp, out SSN ssn) {
var r = int.TryParse (spn, ifp, out var n);
ssn = new SSN (r ? n : default);
return r;
}
}
#endif |
Beta Was this translation helpful? Give feedback.
We have a general issue tracking trailing commas: #391
This should be rolled into that.