diff --git a/eng/Versions.props b/eng/Versions.props
index 1c8ae0b1d33b0..cdb313d0a0654 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -17,6 +17,8 @@
release
true
+
+ 4.0.0-2.21323.11
true
false
false
diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props
index 67a5eab17c868..08fca8de6dd64 100644
--- a/src/coreclr/clr.featuredefines.props
+++ b/src/coreclr/clr.featuredefines.props
@@ -9,6 +9,7 @@
true
true
true
+ true
true
@@ -58,7 +59,8 @@
$(DefineConstants);FEATURE_BASICFREEZE
$(DefineConstants);FEATURE_PORTABLE_SHUFFLE_THUNKS
$(DefineConstants);FEATURE_ICASTABLE
-
+ $(DefineConstants);FEATURE_GENERIC_MATH
+
$(DefineConstants);PROFILING_SUPPORTED
$(DefineConstants);FEATURE_PROFAPI_ATTACH_DETACH
diff --git a/src/coreclr/vm/typedesc.cpp b/src/coreclr/vm/typedesc.cpp
index fbc6ff0170ece..f8567e0a9aa35 100644
--- a/src/coreclr/vm/typedesc.cpp
+++ b/src/coreclr/vm/typedesc.cpp
@@ -1730,6 +1730,11 @@ BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstra
}
CONTRACTL_END;
+ // During EEStartup, we cannot safely validate constraints, but we can also be confident that the code doesn't violate them
+ // Just skip validation and declare that the constraints are satisfied.
+ if (g_fEEInit)
+ return TRUE;
+
IMDInternalImport* pInternalImport = GetModule()->GetMDImport();
mdGenericParamConstraint tkConstraint;
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index 1ceea5e5c0cc9..57d2b9b858691 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -2257,4 +2257,27 @@
Interop\Windows\Kernel32\Interop.Threading.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Byte.cs b/src/libraries/System.Private.CoreLib/src/System/Byte.cs
index 8f127b6cbdd46..39bfeae2a7e44 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Byte.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Byte.cs
@@ -3,6 +3,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
+using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
@@ -13,6 +14,13 @@ namespace System
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly struct Byte : IComparable, IConvertible, ISpanFormattable, IComparable, IEquatable
+#if FEATURE_GENERIC_MATH
+#pragma warning disable SA1001
+ , IBinaryInteger,
+ IMinMaxValue,
+ IUnsignedNumber
+#pragma warning restore SA1001
+#endif // FEATURE_GENERIC_MATH
{
private readonly byte m_value; // Do not rename (binary serialization)
@@ -22,7 +30,6 @@ namespace System
// The minimum value that a Byte may represent: 0.
public const byte MinValue = 0;
-
// Compares this object to another object, returning an integer that
// indicates the relationship.
// Returns a value less than zero if this object
@@ -190,14 +197,14 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan
}
//
- // IConvertible implementation
+ // IConvertible
//
+
public TypeCode GetTypeCode()
{
return TypeCode.Byte;
}
-
bool IConvertible.ToBoolean(IFormatProvider? provider)
{
return Convert.ToBoolean(m_value);
@@ -272,5 +279,724 @@ object IConvertible.ToType(Type type, IFormatProvider? provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
+
+#if FEATURE_GENERIC_MATH
+ //
+ // IAdditionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IAdditionOperators.operator +(byte left, byte right)
+ => (byte)(left + right);
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IAdditionOperators.operator +(byte left, byte right)
+ // => checked((byte)(left + right));
+
+ //
+ // IAdditiveIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IAdditiveIdentity.AdditiveIdentity => 0;
+
+ //
+ // IBinaryInteger
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IBinaryInteger.LeadingZeroCount(byte value)
+ => (byte)(BitOperations.LeadingZeroCount(value) - 24);
+
+ [RequiresPreviewFeatures]
+ static byte IBinaryInteger.PopCount(byte value)
+ => (byte)BitOperations.PopCount(value);
+
+ [RequiresPreviewFeatures]
+ static byte IBinaryInteger.RotateLeft(byte value, byte rotateAmount)
+ => (byte)((value << (rotateAmount & 7)) | (value >> ((8 - rotateAmount) & 7)));
+
+ [RequiresPreviewFeatures]
+ static byte IBinaryInteger.RotateRight(byte value, byte rotateAmount)
+ => (byte)((value >> (rotateAmount & 7)) | (value << ((8 - rotateAmount) & 7)));
+
+ [RequiresPreviewFeatures]
+ static byte IBinaryInteger.TrailingZeroCount(byte value)
+ => (byte)(BitOperations.TrailingZeroCount(value << 24) - 24);
+
+ //
+ // IBinaryNumber
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IBinaryNumber.IsPow2(byte value)
+ => BitOperations.IsPow2((uint)value);
+
+ [RequiresPreviewFeatures]
+ static byte IBinaryNumber.Log2(byte value)
+ => (byte)BitOperations.Log2(value);
+
+ //
+ // IBitwiseOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IBitwiseOperators.operator &(byte left, byte right)
+ => (byte)(left & right);
+
+ [RequiresPreviewFeatures]
+ static byte IBitwiseOperators.operator |(byte left, byte right)
+ => (byte)(left | right);
+
+ [RequiresPreviewFeatures]
+ static byte IBitwiseOperators.operator ^(byte left, byte right)
+ => (byte)(left ^ right);
+
+ [RequiresPreviewFeatures]
+ static byte IBitwiseOperators.operator ~(byte value)
+ => (byte)(~value);
+
+ //
+ // IComparisonOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <(byte left, byte right)
+ => left < right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <=(byte left, byte right)
+ => left <= right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >(byte left, byte right)
+ => left > right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >=(byte left, byte right)
+ => left >= right;
+
+ //
+ // IDecrementOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IDecrementOperators.operator --(byte value)
+ => value--;
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IDecrementOperators.operator --(byte value)
+ // => checked(value--);
+
+ //
+ // IDivisionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IDivisionOperators.operator /(byte left, byte right)
+ => (byte)(left / right);
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IDivisionOperators.operator /(byte left, byte right)
+ // => checked((byte)(left / right));
+
+ //
+ // IEqualityOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator ==(byte left, byte right)
+ => left == right;
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator !=(byte left, byte right)
+ => left != right;
+
+ //
+ // IIncrementOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IIncrementOperators.operator ++(byte value)
+ => value++;
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IIncrementOperators.operator ++(byte value)
+ // => checked(value++);
+
+ //
+ // IMinMaxValue
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IMinMaxValue.MinValue => MinValue;
+
+ [RequiresPreviewFeatures]
+ static byte IMinMaxValue.MaxValue => MaxValue;
+
+ //
+ // IModulusOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IModulusOperators.operator %(byte left, byte right)
+ => (byte)(left % right);
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IModulusOperators.operator %(byte left, byte right)
+ // => checked((byte)(left % right));
+
+ //
+ // IMultiplicativeIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IMultiplicativeIdentity.MultiplicativeIdentity => 1;
+
+ //
+ // IMultiplyOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IMultiplyOperators.operator *(byte left, byte right)
+ => (byte)(left * right);
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IMultiplyOperators.operator *(byte left, byte right)
+ // => checked((byte)(left * right));
+
+ //
+ // INumber
+ //
+
+ [RequiresPreviewFeatures]
+ static byte INumber.One => 1;
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Zero => 0;
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Abs(byte value)
+ => value;
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Clamp(byte value, byte min, byte max)
+ => Math.Clamp(value, min, max);
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static byte INumber.Create(TOther value)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ return (byte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ return checked((byte)(char)(object)value);
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ return checked((byte)(decimal)(object)value);
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ return checked((byte)(double)(object)value);
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ return checked((byte)(short)(object)value);
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ return checked((byte)(int)(object)value);
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ return checked((byte)(long)(object)value);
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ return checked((byte)(nint)(object)value);
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ return checked((byte)(sbyte)(object)value);
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ return checked((byte)(float)(object)value);
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ return checked((byte)(ushort)(object)value);
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ return checked((byte)(uint)(object)value);
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ return checked((byte)(ulong)(object)value);
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ return checked((byte)(nuint)(object)value);
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ return default;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static byte INumber.CreateSaturating(TOther value)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ return (byte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ var actualValue = (char)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ var actualValue = (decimal)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ var actualValue = (double)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ var actualValue = (short)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ var actualValue = (int)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ var actualValue = (long)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ var actualValue = (nint)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ var actualValue = (sbyte)(object)value;
+ return (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ var actualValue = (float)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < 0) ? MinValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ var actualValue = (ushort)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ var actualValue = (uint)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ var actualValue = (ulong)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (byte)actualValue;
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ var actualValue = (nuint)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (byte)actualValue;
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ return default;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static byte INumber.CreateTruncating(TOther value)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ return (byte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ return (byte)(char)(object)value;
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ return (byte)(decimal)(object)value;
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ return (byte)(double)(object)value;
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ return (byte)(short)(object)value;
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ return (byte)(int)(object)value;
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ return (byte)(long)(object)value;
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ return (byte)(nint)(object)value;
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ return (byte)(sbyte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ return (byte)(float)(object)value;
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ return (byte)(ushort)(object)value;
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ return (byte)(uint)(object)value;
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ return (byte)(ulong)(object)value;
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ return (byte)(nuint)(object)value;
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ return default;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ static (byte Quotient, byte Remainder) INumber.DivRem(byte left, byte right)
+ => Math.DivRem(left, right);
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Max(byte x, byte y)
+ => Math.Max(x, y);
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Min(byte x, byte y)
+ => Math.Min(x, y);
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Parse(string s, NumberStyles style, IFormatProvider? provider)
+ => Parse(s, style, provider);
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider)
+ => Parse(s, style, provider);
+
+ [RequiresPreviewFeatures]
+ static byte INumber.Sign(byte value)
+ => (byte)((value == 0) ? 0 : 1);
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static bool INumber.TryCreate(TOther value, out byte result)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ result = (byte)(object)value;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ var actualValue = (char)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ var actualValue = (decimal)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ var actualValue = (double)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ var actualValue = (short)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ var actualValue = (int)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ var actualValue = (long)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ var actualValue = (nint)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ var actualValue = (sbyte)(object)value;
+
+ if (actualValue < 0)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ var actualValue = (float)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ var actualValue = (ushort)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ var actualValue = (uint)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ var actualValue = (ulong)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ var actualValue = (nuint)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (byte)actualValue;
+ return true;
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ result = default;
+ return false;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out byte result)
+ => TryParse(s, style, provider, out result);
+
+ [RequiresPreviewFeatures]
+ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out byte result)
+ => TryParse(s, style, provider, out result);
+
+ //
+ // IParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IParseable.Parse(string s, IFormatProvider? provider)
+ => Parse(s, provider);
+
+ [RequiresPreviewFeatures]
+ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out byte result)
+ => TryParse(s, NumberStyles.Integer, provider, out result);
+
+ //
+ // IShiftOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IShiftOperators.operator <<(byte value, int shiftAmount)
+ => (byte)(value << shiftAmount);
+
+ [RequiresPreviewFeatures]
+ static byte IShiftOperators.operator >>(byte value, int shiftAmount)
+ => (byte)(value >> shiftAmount);
+
+ // [RequiresPreviewFeatures]
+ // static byte IShiftOperators.operator >>>(byte value, int shiftAmount)
+ // => (byte)(value >> shiftAmount);
+
+ //
+ // ISpanParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static byte ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider)
+ => Parse(s, NumberStyles.Integer, provider);
+
+ [RequiresPreviewFeatures]
+ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out byte result)
+ => TryParse(s, NumberStyles.Integer, provider, out result);
+
+ //
+ // ISubtractionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte ISubtractionOperators.operator -(byte left, byte right)
+ => (byte)(left - right);
+
+ // [RequiresPreviewFeatures]
+ // static checked byte ISubtractionOperators.operator -(byte left, byte right)
+ // => checked((byte)(left - right));
+
+ //
+ // IUnaryNegationOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IUnaryNegationOperators.operator -(byte value)
+ => (byte)(-value);
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IUnaryNegationOperators.operator -(byte value)
+ // => checked((byte)(-value));
+
+ //
+ // IUnaryPlusOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static byte IUnaryPlusOperators.operator +(byte value)
+ => (byte)(+value);
+
+ // [RequiresPreviewFeatures]
+ // static checked byte IUnaryPlusOperators.operator +(byte value)
+ // => checked((byte)(+value));
+#endif // FEATURE_GENERIC_MATH
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs
index 613d0909429d4..2f58b54b7460a 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Char.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs
@@ -14,7 +14,10 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
+using System.Numerics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
using System.Text;
namespace System
@@ -23,6 +26,13 @@ namespace System
[StructLayout(LayoutKind.Sequential)]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly struct Char : IComparable, IComparable, IEquatable, IConvertible, ISpanFormattable
+#if FEATURE_GENERIC_MATH
+#pragma warning disable SA1001
+ , IBinaryInteger,
+ IMinMaxValue,
+ IUnsignedNumber
+#pragma warning restore SA1001
+#endif // FEATURE_GENERIC_MATH
{
//
// Member Variables
@@ -1049,5 +1059,741 @@ public static int ConvertToUtf32(string s, int index)
// Not a high-surrogate or low-surrogate. Genereate the UTF32 value for the BMP characters.
return (int)s[index];
}
+
+#if FEATURE_GENERIC_MATH
+ //
+ // IAdditionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IAdditionOperators.operator +(char left, char right)
+ => (char)(left + right);
+
+ // [RequiresPreviewFeatures]
+ // static checked char IAdditionOperators.operator +(char left, char right)
+ // => checked((char)(left + right));
+
+ //
+ // IAdditiveIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static char IAdditiveIdentity.AdditiveIdentity => (char)0;
+
+ //
+ // IBinaryInteger
+ //
+
+ [RequiresPreviewFeatures]
+ static char IBinaryInteger.LeadingZeroCount(char value)
+ => (char)(BitOperations.LeadingZeroCount(value) - 16);
+
+ [RequiresPreviewFeatures]
+ static char IBinaryInteger.PopCount(char value)
+ => (char)BitOperations.PopCount(value);
+
+ [RequiresPreviewFeatures]
+ static char IBinaryInteger.RotateLeft(char value, char rotateAmount)
+ => (char)((value << (rotateAmount & 15)) | (value >> ((16 - rotateAmount) & 15)));
+
+ [RequiresPreviewFeatures]
+ static char IBinaryInteger.RotateRight(char value, char rotateAmount)
+ => (char)((value >> (rotateAmount & 15)) | (value << ((16 - rotateAmount) & 15)));
+
+ [RequiresPreviewFeatures]
+ static char IBinaryInteger.TrailingZeroCount(char value)
+ => (char)(BitOperations.TrailingZeroCount(value << 16) - 16);
+
+ //
+ // IBinaryNumber
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IBinaryNumber.IsPow2(char value)
+ => BitOperations.IsPow2((uint)value);
+
+ [RequiresPreviewFeatures]
+ static char IBinaryNumber.Log2(char value)
+ => (char)BitOperations.Log2(value);
+
+ //
+ // IBitwiseOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IBitwiseOperators.operator &(char left, char right)
+ => (char)(left & right);
+
+ [RequiresPreviewFeatures]
+ static char IBitwiseOperators.operator |(char left, char right)
+ => (char)(left | right);
+
+ [RequiresPreviewFeatures]
+ static char IBitwiseOperators.operator ^(char left, char right)
+ => (char)(left ^ right);
+
+ [RequiresPreviewFeatures]
+ static char IBitwiseOperators.operator ~(char value)
+ => (char)(~value);
+
+ //
+ // IComparisonOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <(char left, char right)
+ => left < right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <=(char left, char right)
+ => left <= right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >(char left, char right)
+ => left > right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >=(char left, char right)
+ => left >= right;
+
+ //
+ // IDecrementOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IDecrementOperators.operator --(char value)
+ => value--;
+
+ // [RequiresPreviewFeatures]
+ // static checked char IDecrementOperators.operator --(char value)
+ // => checked(value--);
+
+ //
+ // IDivisionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IDivisionOperators.operator /(char left, char right)
+ => (char)(left / right);
+
+ // [RequiresPreviewFeatures]
+ // static checked char IDivisionOperators.operator /(char left, char right)
+ // => checked((char)(left / right));
+
+ //
+ // IEqualityOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator ==(char left, char right)
+ => left == right;
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator !=(char left, char right)
+ => left != right;
+
+ //
+ // IIncrementOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IIncrementOperators.operator ++(char value)
+ => value++;
+
+ // [RequiresPreviewFeatures]
+ // static checked char IIncrementOperators.operator ++(char value)
+ // => checked(value++);
+
+ //
+ // IMinMaxValue
+ //
+
+ [RequiresPreviewFeatures]
+ static char IMinMaxValue.MinValue => MinValue;
+
+ [RequiresPreviewFeatures]
+ static char IMinMaxValue.MaxValue => MaxValue;
+
+ //
+ // IModulusOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IModulusOperators.operator %(char left, char right)
+ => (char)(left % right);
+
+ // [RequiresPreviewFeatures]
+ // static checked char IModulusOperators.operator %(char left, char right)
+ // => checked((char)(left % right));
+
+ //
+ // IMultiplicativeIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static char IMultiplicativeIdentity.MultiplicativeIdentity => (char)1;
+
+ //
+ // IMultiplyOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IMultiplyOperators.operator *(char left, char right)
+ => (char)(left * right);
+
+ // [RequiresPreviewFeatures]
+ // static checked char IMultiplyOperators.operator *(char left, char right)
+ // => checked((char)(left * right));
+
+ //
+ // INumber
+ //
+
+ [RequiresPreviewFeatures]
+ static char INumber.One => (char)1;
+
+ [RequiresPreviewFeatures]
+ static char INumber.Zero => (char)0;
+
+ [RequiresPreviewFeatures]
+ static char INumber.Abs(char value)
+ => value;
+
+ [RequiresPreviewFeatures]
+ static char INumber.Clamp(char value, char min, char max)
+ => (char)Math.Clamp(value, min, max);
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static char INumber.Create(TOther value)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ return (char)(byte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ return (char)(object)value;
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ return checked((char)(decimal)(object)value);
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ return checked((char)(double)(object)value);
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ return checked((char)(short)(object)value);
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ return checked((char)(int)(object)value);
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ return checked((char)(long)(object)value);
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ return checked((char)(nint)(object)value);
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ return checked((char)(sbyte)(object)value);
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ return checked((char)(float)(object)value);
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ return (char)(ushort)(object)value;
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ return checked((char)(uint)(object)value);
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ return checked((char)(ulong)(object)value);
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ return checked((char)(nuint)(object)value);
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ return default;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static char INumber.CreateSaturating(TOther value)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ return (char)(byte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ return (char)(object)value;
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ var actualValue = (decimal)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ var actualValue = (double)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ var actualValue = (short)(object)value;
+ return (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ var actualValue = (int)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ var actualValue = (long)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ var actualValue = (nint)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ var actualValue = (sbyte)(object)value;
+ return (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ var actualValue = (float)(object)value;
+ return (actualValue > MaxValue) ? MaxValue :
+ (actualValue < MinValue) ? MinValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ return (char)(ushort)(object)value;
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ var actualValue = (uint)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ var actualValue = (ulong)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (char)actualValue;
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ var actualValue = (nuint)(object)value;
+ return (actualValue > MaxValue) ? MaxValue : (char)actualValue;
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ return default;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static char INumber.CreateTruncating(TOther value)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ return (char)(byte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ return (char)(object)value;
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ return (char)(decimal)(object)value;
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ return (char)(double)(object)value;
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ return (char)(short)(object)value;
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ return (char)(int)(object)value;
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ return (char)(long)(object)value;
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ return (char)(nint)(object)value;
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ return (char)(sbyte)(object)value;
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ return (char)(float)(object)value;
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ return (char)(ushort)(object)value;
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ return (char)(uint)(object)value;
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ return (char)(ulong)(object)value;
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ return (char)(nuint)(object)value;
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ return default;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ static (char Quotient, char Remainder) INumber.DivRem(char left, char right)
+ => ((char, char))Math.DivRem(left, right);
+
+ [RequiresPreviewFeatures]
+ static char INumber.Max(char x, char y)
+ => (char)Math.Max(x, y);
+
+ [RequiresPreviewFeatures]
+ static char INumber.Min(char x, char y)
+ => (char)Math.Min(x, y);
+
+ [RequiresPreviewFeatures]
+ static char INumber.Parse(string s, NumberStyles style, IFormatProvider? provider)
+ => Parse(s);
+
+ [RequiresPreviewFeatures]
+ static char INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider)
+ {
+ if (s.Length != 1)
+ {
+ throw new FormatException(SR.Format_NeedSingleChar);
+ }
+ return s[0];
+ }
+
+ [RequiresPreviewFeatures]
+ static char INumber.Sign(char value)
+ => (char)((value == 0) ? 0 : 1);
+
+ [RequiresPreviewFeatures]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static bool INumber.TryCreate(TOther value, out char result)
+ {
+ if (typeof(TOther) == typeof(byte))
+ {
+ result = (char)(byte)(object)value;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(char))
+ {
+ result = (char)(object)value;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(decimal))
+ {
+ var actualValue = (decimal)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(double))
+ {
+ var actualValue = (double)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(short))
+ {
+ var actualValue = (short)(object)value;
+
+ if (actualValue < 0)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(int))
+ {
+ var actualValue = (int)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(long))
+ {
+ var actualValue = (long)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(nint))
+ {
+ var actualValue = (nint)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(sbyte))
+ {
+ var actualValue = (sbyte)(object)value;
+
+ if (actualValue < 0)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(float))
+ {
+ var actualValue = (float)(object)value;
+
+ if ((actualValue < 0) || (actualValue > MaxValue))
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(ushort))
+ {
+ var actualValue = (ushort)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(uint))
+ {
+ var actualValue = (uint)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(ulong))
+ {
+ var actualValue = (ulong)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else if (typeof(TOther) == typeof(nuint))
+ {
+ var actualValue = (nuint)(object)value;
+
+ if (actualValue > MaxValue)
+ {
+ result = default;
+ return false;
+ }
+
+ result = (char)actualValue;
+ return true;
+ }
+ else
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ result = default;
+ return false;
+ }
+ }
+
+ [RequiresPreviewFeatures]
+ static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out char result)
+ => TryParse(s, out result);
+
+ [RequiresPreviewFeatures]
+ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out char result)
+ {
+ if (s.Length != 1)
+ {
+ result = default;
+ return false;
+ }
+ result = s[0];
+ return true;
+ }
+
+ //
+ // IParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static char IParseable.Parse(string s, IFormatProvider? provider)
+ => Parse(s);
+
+ [RequiresPreviewFeatures]
+ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out char result)
+ => TryParse(s, out result);
+
+ //
+ // IShiftOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IShiftOperators.operator <<(char value, int shiftAmount)
+ => (char)(value << shiftAmount);
+
+ [RequiresPreviewFeatures]
+ static char IShiftOperators.operator >>(char value, int shiftAmount)
+ => (char)(value >> shiftAmount);
+
+ // [RequiresPreviewFeatures]
+ // static char IShiftOperators.operator >>>(char value, int shiftAmount)
+ // => (char)(value >> shiftAmount);
+
+ //
+ // ISpanParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static char ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider)
+ {
+ if (s.Length != 1)
+ {
+ throw new FormatException(SR.Format_NeedSingleChar);
+ }
+ return s[0];
+ }
+
+ [RequiresPreviewFeatures]
+ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out char result)
+ {
+ if (s.Length != 1)
+ {
+ result = default;
+ return false;
+ }
+ result = s[0];
+ return true;
+ }
+
+ //
+ // ISubtractionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char ISubtractionOperators.operator -(char left, char right)
+ => (char)(left - right);
+
+ // [RequiresPreviewFeatures]
+ // static checked char ISubtractionOperators.operator -(char left, char right)
+ // => checked((char)(left - right));
+
+ //
+ // IUnaryNegationOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IUnaryNegationOperators.operator -(char value)
+ => (char)(-value);
+
+ // [RequiresPreviewFeatures]
+ // static checked char IUnaryNegationOperators.operator -(char value)
+ // => checked((char)(-value));
+
+ //
+ // IUnaryPlusOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static char IUnaryPlusOperators.operator +(char value)
+ => (char)(+value);
+
+ // [RequiresPreviewFeatures]
+ // static checked char IUnaryPlusOperators.operator +(char value)
+ // => checked((char)(+value));
+#endif // FEATURE_GENERIC_MATH
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs
index 1ca9b084ee0aa..7e64638fa5103 100644
--- a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs
@@ -2,8 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
-using System.Globalization;
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Runtime.Versioning;
namespace System
{
@@ -11,6 +12,13 @@ namespace System
/// Represents dates with values ranging from January 1, 0001 Anno Domini (Common Era) through December 31, 9999 A.D. (C.E.) in the Gregorian calendar.
///
public readonly struct DateOnly : IComparable, IComparable, IEquatable, ISpanFormattable
+#if FEATURE_GENERIC_MATH
+#pragma warning disable SA1001
+ , IComparisonOperators,
+ IMinMaxValue,
+ ISpanParseable
+#pragma warning restore SA1001
+#endif // FEATURE_GENERIC_MATH
{
private readonly int _dayNumber;
@@ -822,5 +830,73 @@ public string ToString(string? format, IFormatProvider? provider)
return DateTimeFormat.TryFormat(GetEquivalentDateTime(), destination, out charsWritten, format, provider);
}
+
+#if FEATURE_GENERIC_MATH
+ //
+ // IComparisonOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <(DateOnly left, DateOnly right)
+ => left < right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <=(DateOnly left, DateOnly right)
+ => left <= right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >(DateOnly left, DateOnly right)
+ => left > right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >=(DateOnly left, DateOnly right)
+ => left >= right;
+
+ //
+ // IEqualityOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator ==(DateOnly left, DateOnly right)
+ => left == right;
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator !=(DateOnly left, DateOnly right)
+ => left != right;
+
+ //
+ // IMinMaxValue
+ //
+
+ [RequiresPreviewFeatures]
+ static DateOnly IMinMaxValue.MinValue => MinValue;
+
+ [RequiresPreviewFeatures]
+ static DateOnly IMinMaxValue.MaxValue => MaxValue;
+
+ //
+ // IParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static DateOnly IParseable.Parse(string s, IFormatProvider? provider)
+ => Parse(s, provider, DateTimeStyles.None);
+
+ [RequiresPreviewFeatures]
+ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateOnly result)
+ => TryParse(s, provider, DateTimeStyles.None, out result);
+
+ //
+ // ISpanParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static DateOnly ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider)
+ => Parse(s, provider, DateTimeStyles.None);
+
+ [RequiresPreviewFeatures]
+ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateOnly result)
+ => TryParse(s, provider, DateTimeStyles.None, out result);
+#endif // FEATURE_GENERIC_MATH
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs
index dc2ebdf1380df..1d0235268a14e 100644
--- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs
@@ -7,6 +7,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
+using System.Runtime.Versioning;
namespace System
{
@@ -44,6 +45,17 @@ namespace System
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly partial struct DateTime : IComparable, ISpanFormattable, IConvertible, IComparable, IEquatable, ISerializable
+#if FEATURE_GENERIC_MATH
+#pragma warning disable SA1001
+ , IAdditionOperators,
+ IAdditiveIdentity,
+ IComparisonOperators,
+ IMinMaxValue,
+ ISpanParseable,
+ ISubtractionOperators,
+ ISubtractionOperators
+#pragma warning restore SA1001
+#endif // FEATURE_GENERIC_MATH
{
// Number of 100ns ticks per time unit
private const long TicksPerMillisecond = 10000;
@@ -1503,5 +1515,113 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut
result = new DateTime(ticks);
return true;
}
+
+#if FEATURE_GENERIC_MATH
+ //
+ // IAdditionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTime IAdditionOperators.operator +(DateTime left, TimeSpan right)
+ => left + right;
+
+ // [RequiresPreviewFeatures]
+ // static checked DateTime IAdditionOperators.operator +(DateTime left, TimeSpan right)
+ // => checked(left + right);
+
+ //
+ // IAdditiveIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static TimeSpan IAdditiveIdentity.AdditiveIdentity
+ => default;
+
+ //
+ // IComparisonOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <(DateTime left, DateTime right)
+ => left < right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <=(DateTime left, DateTime right)
+ => left <= right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >(DateTime left, DateTime right)
+ => left > right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >=(DateTime left, DateTime right)
+ => left >= right;
+
+ //
+ // IEqualityOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator ==(DateTime left, DateTime right)
+ => left == right;
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator !=(DateTime left, DateTime right)
+ => left != right;
+
+ //
+ // IMinMaxValue
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTime IMinMaxValue.MinValue => MinValue;
+
+ [RequiresPreviewFeatures]
+ static DateTime IMinMaxValue.MaxValue => MaxValue;
+
+ //
+ // IParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTime IParseable.Parse(string s, IFormatProvider? provider)
+ => Parse(s, provider);
+
+ [RequiresPreviewFeatures]
+ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateTime result)
+ => TryParse(s, provider, DateTimeStyles.None, out result);
+
+ //
+ // ISpanParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTime ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider)
+ => Parse(s, provider, DateTimeStyles.None);
+
+ [RequiresPreviewFeatures]
+ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateTime result)
+ => TryParse(s, provider, DateTimeStyles.None, out result);
+
+ //
+ // ISubtractionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTime ISubtractionOperators.operator -(DateTime left, TimeSpan right)
+ => left - right;
+
+ // [RequiresPreviewFeatures]
+ // static checked DateTime ISubtractionOperators.operator -(DateTime left, TimeSpan right)
+ // => checked(left - right);
+
+ [RequiresPreviewFeatures]
+ static TimeSpan ISubtractionOperators.operator -(DateTime left, DateTime right)
+ => left - right;
+
+ // [RequiresPreviewFeatures]
+ // static checked TimeSpan ISubtractionOperators.operator -(DateTime left, DateTime right)
+ // => checked(left - right);
+#endif // FEATURE_GENERIC_MATH
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs
index 8b91fd6a2a8f3..f9fcc33b9a0cf 100644
--- a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs
@@ -6,6 +6,7 @@
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
+using System.Runtime.Versioning;
namespace System
{
@@ -32,6 +33,17 @@ namespace System
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly struct DateTimeOffset : IComparable, ISpanFormattable, IComparable, IEquatable, ISerializable, IDeserializationCallback
+#if FEATURE_GENERIC_MATH
+#pragma warning disable SA1001
+ , IAdditionOperators,
+ IAdditiveIdentity,
+ IComparisonOperators,
+ IMinMaxValue,
+ ISpanParseable,
+ ISubtractionOperators,
+ ISubtractionOperators
+#pragma warning restore SA1001
+#endif // FEATURE_GENERIC_MATH
{
// Constants
internal const long MaxOffset = TimeSpan.TicksPerHour * 14;
@@ -852,5 +864,112 @@ public static implicit operator DateTimeOffset(DateTime dateTime) =>
public static bool operator >=(DateTimeOffset left, DateTimeOffset right) =>
left.UtcDateTime >= right.UtcDateTime;
+
+#if FEATURE_GENERIC_MATH
+ //
+ // IAdditionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTimeOffset IAdditionOperators.operator +(DateTimeOffset left, TimeSpan right)
+ => left + right;
+
+ // [RequiresPreviewFeatures]
+ // static checked DateTimeOffset IAdditionOperators.operator +(DateTimeOffset left, TimeSpan right)
+ // => checked(left + right);
+
+ //
+ // IAdditiveIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static TimeSpan IAdditiveIdentity.AdditiveIdentity => default;
+
+ //
+ // IComparisonOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <(DateTimeOffset left, DateTimeOffset right)
+ => left < right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <=(DateTimeOffset left, DateTimeOffset right)
+ => left <= right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >(DateTimeOffset left, DateTimeOffset right)
+ => left > right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >=(DateTimeOffset left, DateTimeOffset right)
+ => left >= right;
+
+ //
+ // IEqualityOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator ==(DateTimeOffset left, DateTimeOffset right)
+ => left == right;
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator !=(DateTimeOffset left, DateTimeOffset right)
+ => left != right;
+
+ //
+ // IMinMaxValue
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTimeOffset IMinMaxValue.MinValue => MinValue;
+
+ [RequiresPreviewFeatures]
+ static DateTimeOffset IMinMaxValue.MaxValue => MaxValue;
+
+ //
+ // IParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTimeOffset IParseable.Parse(string s, IFormatProvider? provider)
+ => Parse(s, provider);
+
+ [RequiresPreviewFeatures]
+ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateTimeOffset result)
+ => TryParse(s, provider, DateTimeStyles.None, out result);
+
+ //
+ // ISpanParseable
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTimeOffset ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider)
+ => Parse(s, provider, DateTimeStyles.None);
+
+ [RequiresPreviewFeatures]
+ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateTimeOffset result)
+ => TryParse(s, provider, DateTimeStyles.None, out result);
+
+ //
+ // ISubtractionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static DateTimeOffset ISubtractionOperators.operator -(DateTimeOffset left, TimeSpan right)
+ => left - right;
+
+ // [RequiresPreviewFeatures]
+ // static checked DateTimeOffset ISubtractionOperators.operator -(DateTimeOffset left, TimeSpan right)
+ // => checked(left - right);
+
+ [RequiresPreviewFeatures]
+ static TimeSpan ISubtractionOperators.operator -(DateTimeOffset left, DateTimeOffset right)
+ => left - right;
+
+ // [RequiresPreviewFeatures]
+ // static checked TimeSpan ISubtractionOperators.operator -(DateTimeOffset left, DateTimeOffset right)
+ // => checked(left - right);
+#endif // FEATURE_GENERIC_MATH
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs
index 429d4c3cdf6a9..e5f26f2ff0148 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs
@@ -8,6 +8,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
+using System.Runtime.Versioning;
namespace System
{
@@ -58,6 +59,12 @@ namespace System
[System.Runtime.Versioning.NonVersionable] // This only applies to field layout
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly partial struct Decimal : ISpanFormattable, IComparable, IConvertible, IComparable, IEquatable, ISerializable, IDeserializationCallback
+#if FEATURE_GENERIC_MATH
+#pragma warning disable SA1001
+ , IMinMaxValue,
+ ISignedNumber
+#pragma warning restore SA1001
+#endif // FEATURE_GENERIC_MATH
{
// Sign mask for the flags field. A value of zero in this bit indicates a
// positive Decimal value, and a value of one in this bit indicates a
@@ -1072,5 +1079,535 @@ object IConvertible.ToType(Type type, IFormatProvider? provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
+
+#if FEATURE_GENERIC_MATH
+ //
+ // IAdditionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IAdditionOperators.operator +(decimal left, decimal right)
+ => checked(left + right);
+
+ // [RequiresPreviewFeatures]
+ // static checked decimal IAdditionOperators.operator +(decimal left, decimal right)
+ // => checked(left + right);
+
+ //
+ // IAdditiveIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IAdditiveIdentity.AdditiveIdentity => 0.0m;
+
+ //
+ // IComparisonOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <(decimal left, decimal right)
+ => left < right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator <=(decimal left, decimal right)
+ => left <= right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >(decimal left, decimal right)
+ => left > right;
+
+ [RequiresPreviewFeatures]
+ static bool IComparisonOperators.operator >=(decimal left, decimal right)
+ => left >= right;
+
+ //
+ // IDecrementOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IDecrementOperators.operator --(decimal value)
+ => value--;
+
+ // [RequiresPreviewFeatures]
+ // static checked decimal IDecrementOperators.operator --(decimal value)
+ // => checked(value--);
+
+ //
+ // IDivisionOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IDivisionOperators.operator /(decimal left, decimal right)
+ => left / right;
+
+ // [RequiresPreviewFeatures]
+ // static checked decimal IDivisionOperators.operator /(decimal left, decimal right)
+ // => checked(left / right);
+
+ //
+ // IEqualityOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator ==(decimal left, decimal right)
+ => left == right;
+
+ [RequiresPreviewFeatures]
+ static bool IEqualityOperators.operator !=(decimal left, decimal right)
+ => left != right;
+
+ //
+ // IIncrementOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IIncrementOperators.operator ++(decimal value)
+ => value++;
+
+ // [RequiresPreviewFeatures]
+ // static checked decimal IIncrementOperators.operator ++(decimal value)
+ // => checked(value++);
+
+ //
+ // IMinMaxValue
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IMinMaxValue.MinValue => MinValue;
+
+ [RequiresPreviewFeatures]
+ static decimal IMinMaxValue.MaxValue => MaxValue;
+
+ //
+ // IModulusOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IModulusOperators.operator %(decimal left, decimal right)
+ => left % right;
+
+ // [RequiresPreviewFeatures]
+ // static checked decimal IModulusOperators.operator %(decimal left, decimal right)
+ // => checked(left % right);
+
+ //
+ // IMultiplicativeIdentity
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IMultiplicativeIdentity.MultiplicativeIdentity => 1.0m;
+
+ //
+ // IMultiplyOperators
+ //
+
+ [RequiresPreviewFeatures]
+ static decimal IMultiplyOperators