diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/ref/System.Runtime.InteropServices.RuntimeInformation.cs b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/ref/System.Runtime.InteropServices.RuntimeInformation.cs
index aae34f0b6a70e4..5bba24994424d7 100644
--- a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/ref/System.Runtime.InteropServices.RuntimeInformation.cs
+++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/ref/System.Runtime.InteropServices.RuntimeInformation.cs
@@ -39,5 +39,15 @@ public static partial class RuntimeInformation
public static string OSDescription { get { throw null; } }
public static System.Runtime.InteropServices.Architecture ProcessArchitecture { get { throw null; } }
public static bool IsOSPlatform(System.Runtime.InteropServices.OSPlatform osPlatform) { throw null; }
+ public static bool IsOSPlatformOrLater(string platformName) { throw null; }
+ public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major) { throw null; }
+ public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor) { throw null; }
+ public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build) { throw null; }
+ public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build, int revision) { throw null; }
+ public static bool IsOSPlatformEarlierThan(string platformName) { throw null; }
+ public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major) { throw null; }
+ public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor) { throw null; }
+ public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build) { throw null; }
+ public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build, int revision) { throw null; }
}
}
diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/Resources/Strings.resx
index e554cfe1fe2eb1..c7f9079719cce4 100644
--- a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/Resources/Strings.resx
+++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/Resources/Strings.resx
@@ -60,6 +60,9 @@
Value cannot be empty.
+
+ "{0}" is not a valid platform name. It must contain both name and version (with at least major and minor number specified). Example: "ios14.0".
+
RuntimeInformation is not supported for Portable Class Libraries.
diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System.Runtime.InteropServices.RuntimeInformation.csproj b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System.Runtime.InteropServices.RuntimeInformation.csproj
index 7b46386905a072..402c6678843b96 100644
--- a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System.Runtime.InteropServices.RuntimeInformation.csproj
+++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System.Runtime.InteropServices.RuntimeInformation.csproj
@@ -7,6 +7,7 @@
+
@@ -45,5 +46,6 @@
+
diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.PlatformVersion.cs b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.PlatformVersion.cs
new file mode 100644
index 00000000000000..0eec21939bfa82
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.PlatformVersion.cs
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.InteropServices
+{
+ public static partial class RuntimeInformation
+ {
+ ///
+ /// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
+ ///
+ /// OS name concatenated with a version number.
+ /// The version number must contain at least major and minor numbers separated with a dot.
+ /// Example: "ios14.0" is OK, "ios14" is NOT OK.
+ public static bool IsOSPlatformOrLater(string platformName)
+ {
+ (OSPlatform platform, Version version) = Parse(platformName);
+
+ return IsOSPlatformOrLater(platform, version.Major, version.Minor, version.Build, version.Revision);
+ }
+
+ ///
+ /// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
+ ///
+ public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major)
+ => IsOSPlatform(osPlatform) && Environment.OSVersion.Version.Major >= major;
+
+ ///
+ /// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
+ ///
+ public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major, int minor)
+ => IsOSPlatform(osPlatform) && IsOSVersionOrLater(major, minor, int.MinValue, int.MinValue);
+
+ ///
+ /// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
+ ///
+ public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major, int minor, int build)
+ => IsOSPlatform(osPlatform) && IsOSVersionOrLater(major, minor, build, int.MinValue);
+
+ ///
+ /// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
+ ///
+ public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major, int minor, int build, int revision)
+ => IsOSPlatform(osPlatform) && IsOSVersionOrLater(major, minor, build, revision);
+
+ ///
+ /// Check for the OS with a < version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
+ ///
+ /// OS name concatenated with a version number.
+ /// The version number must contain at least major and minor numbers separated with a dot.
+ /// Example: "ios14.0" is OK, "ios14" is NOT OK.
+ public static bool IsOSPlatformEarlierThan(string platformName)
+ {
+ (OSPlatform platform, Version version) = Parse(platformName);
+
+ return IsOSPlatformEarlierThan(platform, version.Major, version.Minor, version.Build, version.Revision);
+ }
+
+ ///
+ /// Check for the OS with a < version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
+ ///
+ public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major)
+ => IsOSPlatform(osPlatform) && Environment.OSVersion.Version.Major < major;
+
+ ///
+ /// Check for the OS with a < version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
+ ///
+ public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major, int minor)
+ => IsOSPlatform(osPlatform) && !IsOSVersionOrLater(major, minor, int.MinValue, int.MinValue);
+
+ ///
+ /// Check for the OS with a < version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
+ ///
+ public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major, int minor, int build)
+ => IsOSPlatform(osPlatform) && !IsOSVersionOrLater(major, minor, build, int.MinValue);
+
+ ///
+ /// Check for the OS with a < version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
+ ///
+ public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major, int minor, int build, int revision)
+ => IsOSPlatform(osPlatform) && !IsOSVersionOrLater(major, minor, build, revision);
+
+ private static bool IsOSVersionOrLater(int major, int minor, int build, int revision)
+ {
+ Version current = Environment.OSVersion.Version;
+ if (current.Major != major)
+ {
+ return current.Major > major;
+ }
+ if (current.Minor != minor)
+ {
+ return current.Minor > minor;
+ }
+ if (current.Build != build)
+ {
+ return current.Build > build;
+ }
+
+ return current.Revision >= revision;
+ }
+
+ private static (OSPlatform, Version) Parse(string platformName)
+ {
+ if (platformName == null)
+ {
+ throw new ArgumentNullException(nameof(platformName));
+ }
+ if (platformName.Length == 0)
+ {
+ throw new ArgumentException(SR.Argument_EmptyValue, nameof(platformName));
+ }
+
+ // iterate from the begining, as digits in the middle of the names are not supported by design
+ for (int i = 0; i < platformName.Length; i++)
+ {
+ if (char.IsDigit(platformName[i]))
+ {
+ if (i > 0 && Version.TryParse(platformName.AsSpan(i), out Version? version))
+ {
+ return (OSPlatform.Create(platformName.Substring(0, i)), version);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidPlatfromName, platformName), nameof(platformName));
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/PlatformVersionTests.cs b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/PlatformVersionTests.cs
new file mode 100644
index 00000000000000..c00ace31490338
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/PlatformVersionTests.cs
@@ -0,0 +1,242 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using Xunit;
+
+namespace System.Runtime.InteropServices.RuntimeInformationTests
+{
+ public class PlatformVersionTests
+ {
+ public static IEnumerable