Skip to content

Add breaking change documentation for SYSLIB0061 #45565

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Breaking change: .NET 10 obsoletions with custom IDs"
titleSuffix: ""
description: Learn about the APIs that have been marked as obsolete in .NET 10 with a custom diagnostic ID.
ms.date: 01/14/2025
ms.date: 03/28/2025
ai-usage: ai-assisted
---
# API obsoletions with non-default diagnostic IDs (.NET 10)
Expand All @@ -20,6 +20,7 @@ The following table lists the custom diagnostic IDs and their corresponding warn
| [SYSLIB0058](../../../../fundamentals/syslib-diagnostics/syslib0058.md) | The `KeyExchangeAlgorithm`, `KeyExchangeStrength`, `CipherAlgorithm`, `CipherAlgorithmStrength`, `HashAlgorithm`, and `HashStrength` properties of <xref:System.Net.Security.SslStream> are obsolete. Use <xref:System.Net.Security.SslStream.NegotiatedCipherSuite> instead. | Warning |
| [SYSLIB0059](../../../../fundamentals/syslib-diagnostics/syslib0059.md) | <xref:Microsoft.Win32.SystemEvents.EventsThreadShutdown?displayProperty=nameWithType> callbacks aren't run before the process exits. Use <xref:System.AppDomain.ProcessExit?displayProperty=nameWithType> instead. | Warning |
| [SYSLIB0060](../../../../fundamentals/syslib-diagnostics/syslib0060.md) | <xref:System.Security.Cryptography.Rfc2898DeriveBytes?displayProperty=nameWithType> constructors are obsolete. Use <xref:System.Security.Cryptography.Rfc2898DeriveBytes.Pbkdf2*?displayProperty=nameWithType> instead. | Warning |
| [SYSLIB0061](../../../../fundamentals/syslib-diagnostics/syslib0061.md) | <xref:System.Linq.Queryable.MaxBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=nameWithType> and <xref:System.Linq.Queryable.MinBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=nameWithType> taking an `IComparer<TSource>` are obsolete. Use the new ones that take an `IComparer<TKey>`. | Warning |

## Version introduced

Expand Down Expand Up @@ -58,6 +59,11 @@ These obsoletions can affect [source compatibility](../../categories.md#source-c
- <xref:System.Security.Cryptography.Rfc2898DeriveBytes?displayProperty=fullName>
- <xref:System.Security.Cryptography.Rfc2898DeriveBytes.Pbkdf2*?displayProperty=fullName>

### SYSLIB0061

- <xref:System.Linq.Queryable.MaxBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=fullName>
- <xref:System.Linq.Queryable.MinBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=fullName>

## See also

- [API obsoletions with non-default diagnostic IDs (.NET 9)](../9.0/obsolete-apis-with-custom-diagnostics.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ If you encounter build warnings or errors due to usage of an obsolete API, follo
The following table provides an index to the `SYSLIB0XXX` obsoletions in .NET 5+.

| Diagnostic ID | Warning or error | Description |
| - | - |
|---------------|------------------|-------------|
| [SYSLIB0001](syslib0001.md) | Warning | The UTF-7 encoding is insecure and should not be used. Consider using UTF-8 instead. |
| [SYSLIB0002](syslib0002.md) | Error | <xref:System.Security.Permissions.PrincipalPermissionAttribute> is not honored by the runtime and must not be used. |
| [SYSLIB0003](syslib0003.md) | Warning | Code access security (CAS) is not supported or honored by the runtime. |
Expand Down Expand Up @@ -78,9 +78,10 @@ The following table provides an index to the `SYSLIB0XXX` obsoletions in .NET 5+
| [SYSLIB0055](syslib0055.md) | Warning | `AdvSimd.ShiftRightLogicalRoundedNarrowingSaturate*` methods with signed parameters are obsolete. Use the unsigned overloads instead. |
| [SYSLIB0056](syslib0056.md) | Warning | `Assembly.LoadFrom` with a custom `AssemblyHashAlgorithm` is obsolete. Use overloads without an `AssemblyHashAlgorithm`. |
| [SYSLIB0057](syslib0057.md) | Warning | `X509Certificate2` and `X509Certificate` constructors for binary and file content are obsolete. |
| SYSLIB0058 | Warning | The `KeyExchangeAlgorithm`, `KeyExchangeStrength`, `CipherAlgorithm`, `CipherAlgorithmStrength`, `HashAlgorithm`, and `HashStrength` properties of <xref:System.Net.Security.SslStream> are obsolete. Use <xref:System.Net.Security.SslStream.NegotiatedCipherSuite> instead. |
| [SYSLIB0058](syslib0058.md) | Warning | The `KeyExchangeAlgorithm`, `KeyExchangeStrength`, `CipherAlgorithm`, `CipherAlgorithmStrength`, `HashAlgorithm`, and `HashStrength` properties of <xref:System.Net.Security.SslStream> are obsolete. Use <xref:System.Net.Security.SslStream.NegotiatedCipherSuite> instead. |
| [SYSLIB0059](syslib0059.md) | Warning | <xref:Microsoft.Win32.SystemEvents.EventsThreadShutdown?displayProperty=nameWithType> callbacks aren't run before the process exits. Use <xref:System.AppDomain.ProcessExit?displayProperty=nameWithType> instead. |
| [SYSLIB0060](syslib0060.md) | Warning | Constructors on <xref:System.Security.Cryptography.Rfc2898DeriveBytes?displayProperty=nameWithType> are obsolete. Use <xref:System.Security.Cryptography.Rfc2898DeriveBytes.Pbkdf2%2A?displayProperty=nameWithType> instead. |
| [SYSLIB0061](syslib0061.md) | Warning | The `Queryable` <xref:System.Linq.Queryable.MaxBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=nameWithType> and <xref:System.Linq.Queryable.MinBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=nameWithType> taking an `IComparer<TSource>` are obsolete. Use the new ones that take an `IComparer<TKey>`. |

## Suppress warnings

Expand Down
77 changes: 77 additions & 0 deletions docs/fundamentals/syslib-diagnostics/syslib0061.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: SYSLIB0061 warning - System.Linq.Queryable.MaxBy and System.Linq.Queryable.MinBy accepting an IComparer\<TSource\> are obsolete.
description: Learn about the obsoletion of some MaxBy and MinBy extension methods. Use of these extension methods generates compile-time warning SYSLIB0061.
ms.date: 03/31/2025
f1_keywords:
- SYSLIB0061
---
# SYSLIB0061: System.Linq.Queryable.MaxBy and System.Linq.Queryable.MinBy taking an IComparer\<TSource\> are obsolete.

Starting in .NET 10, the two extension methods <xref:System.Linq.Queryable.MaxBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=fullName> and <xref:System.Linq.Queryable.MinBy``2(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Collections.Generic.IComparer{``0})?displayProperty=fullName> that accept an `IComparer<TSource>` are obsolete. Please use the newly added overloads that accept an `IComparer<TKey>` instead.

Calling these old extension methods in code generates warning `SYSLIB0061` at compile time and typically generates a <xref:System.IndexOutOfRangeException?displayName=nameWithType> at runtime.

## Reason for obsoletion

The original `MaxBy` and `MinBy` accepting an `IComparer<T>? comparer` expression parameter were incorrectly implemented using the generic type `TSource` for the `IComparer<T>? comparer` type parameter. This is incorrect because the values passed to the <xref:System.Collections.Generic.Comparer`1.Compare(`0,`0)?displayProperty=nameWithType> method are selected by the `Expression<Func<TSource, TKey>> keySelector` expression parameter, thus the extracted value is of generic type `TKey`.

### Note

This would previously work only if `TSource` and `TKey` were actually the same constructed type. If the types were distinct then a runtime _<xref:System.IndexOutOfRangeException>: Index was outside the bounds of the array._ would be thrown because the needed extension method for `IQueryable<TSource> source` could not be found (for example in <xref:System.Linq.Enumerable.MaxBy*>).

## Workaround

Use the newly added `MaxBy` or `MinBy` method that accepts an `IComparer<TKey>? comparer` parameter. These will not throw an exception.

For example:

```csharp
// This worked correctly since TKey and TSource are both int.
Enumerable.Range(1, 10)
.AsQueryable()
.MaxBy(key => (0 - key), Comparer<int>.Default);

// This would throw since TKey is string but TSource is int
// and will trigger the obsoletion warning now and would
// throw an exeception at runtime.
Enumerable.Range(1, 10)
.AsQueryable()
.MaxBy(key => key.ToString(), Comparer<int>.Default);

// This previously would not compile before to the addition of
// the new methods since TKey is string and TSource is int.
// It will now compile and execute correctly.
Enumerable.Range(1, 10)
.AsQueryable()
.MaxBy(key => key.ToString(), Comparer<string>.Default);
```

## Suppress a warning

If you must use the obsolete API, you can suppress the warning in code or in your project file.

To suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable the warning.

```csharp
// Disable the warning.
#pragma warning disable SYSLIB0061

// Code that uses obsolete API.
// ...

// Re-enable the warning.
#pragma warning restore SYSLIB0061
```

To suppress all the `SYSLIB0061` warnings in your project, add a `<NoWarn>` property to your project file.

```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<NoWarn>$(NoWarn);SYSLIB0061</NoWarn>
</PropertyGroup>
</Project>
```

For more information, see [Suppress warnings](obsoletions-overview.md#suppress-warnings).
2 changes: 2 additions & 0 deletions docs/navigate/tools-diagnostics/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1837,6 +1837,8 @@ items:
href: ../../fundamentals/syslib-diagnostics/syslib0059.md
- name: SYSLIB0060
href: ../../fundamentals/syslib-diagnostics/syslib0060.md
- name: SYSLIB0061
href: ../../fundamentals/syslib-diagnostics/syslib0061.md
- name: Experimental features
items:
- name: Overview
Expand Down