Skip to content
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

Merge main into live #40196

Merged
merged 4 commits into from
Mar 25, 2024
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
2 changes: 1 addition & 1 deletion docs/azure/includes/dotnet-all.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@
| App Service - API Apps Service | NuGet [0.9.64](https://www.nuget.org/packages/Microsoft.Azure.AppService.ApiApps.Service/0.9.64) | | |
| Code Analyzers for Durable Functions | NuGet [0.5.0](https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.DurableTask.Analyzers/0.5.0) | | GitHub [0.5.0](https://github.com/Azure/azure-functions-durable-extension/tree/Analyzer-v0.3.0/src/WebJobs.Extensions.DurableTask.Analyzers) |
| Cosmos DB - BulkExecutor | NuGet [2.5.1-preview](https://www.nuget.org/packages/Microsoft.Azure.CosmosDB.BulkExecutor/2.5.1-preview) | | GitHub [2.5.1-preview](https://github.com/Azure/azure-cosmosdb-bulkexecutor-dotnet-getting-started) |
| Cosmos DB - Direct | NuGet [3.32.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Direct/3.32.1) | | GitHub [3.32.1](https://github.com/Azure/azure-cosmos-dotnet-v3) |
| Cosmos DB - Direct | NuGet [3.33.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Direct/3.33.0) | | GitHub [3.33.0](https://github.com/Azure/azure-cosmos-dotnet-v3) |
| Cosmos DB - Encryption | NuGet [2.0.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.3)<br>NuGet [2.1.0-preview4](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.1.0-preview4) | | GitHub [2.0.3](https://github.com/Azure/azure-cosmos-dotnet-v3/tree/releases/encryption/1.0.0-preview4/Microsoft.Azure.Cosmos.Encryption) |
| Cosmos DB - Encryption | NuGet [1.0.0-preview06](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview06) | | |
| Extensions - Caching Cosmos | NuGet [1.6.0](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Cosmos/1.6.0) | | GitHub [1.6.0](https://github.com/Azure/Microsoft.Extensions.Caching.Cosmos/tree/v1.0.0-preview4) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Total received: 150 bytes
When `Stream.Read` or `Stream.ReadAsync` was called on one of the affected stream types with a buffer of length `N`, the operation wouldn't complete until:

- `N` bytes had been read from the stream, or
- The underlying stream they wrap returned 0 from a call to its read, indicating no more data was available.
- The underlying stream returned 0 from a call to its read, indicating no more data was available.

Also, when `Stream.Read` or `Stream.ReadAsync` was called with a buffer of length 0, the operation would succeed immediately, sometimes without doing a zero-length read on the stream it wraps.

Expand All @@ -70,7 +70,7 @@ Also, when `Stream.Read` or `Stream.ReadAsync` was called with a buffer of lengt
Starting in .NET 6, when `Stream.Read` or `Stream.ReadAsync` is called on one of the affected stream types with a buffer of length `N`, the operation completes when:

- At least 1 byte has been read from the stream, or
- The underlying stream they wrap returns 0 from a call to its read, indicating no more data is available.
- The underlying stream returns 0 from a call to its read, indicating no more data is available.

Also, when `Stream.Read` or `Stream.ReadAsync` is called with a buffer of length 0, the operation succeeds once a call with a nonzero buffer would succeed.

Expand Down
141 changes: 141 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca1872.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
title: "CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString' (code analysis)"
description: "Learn about code analyzer rule CA1872 - Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'"
ms.date: 03/21/2024
ms.topic: reference
f1_keywords:
- CA1872
- PreferConvertToHexStringOverBitConverterAnalyzer
helpviewer_keywords:
- CA1872
author: mpidash
dev_langs:
- CSharp
- VB
---

# CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'

| | Value |
| ----------------------------------- |---------------------------------------------------------------------------------------------------------------|
| **Rule ID** | CA1872 |
| **Title** | Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString' |
| **Category** | [Performance](performance-warnings.md) |
| **Fix is breaking or non-breaking** | Non-breaking |
| **Enabled by default in .NET 9** | As suggestion |

## Cause

A call to <xref:System.BitConverter.ToString%2A?displayProperty=nameWithType> followed by a call to <xref:System.String.Replace%2A?displayProperty=nameWithType> to remove dashes is used to encode bytes to a hexadecimal string representation.
This rule also fires if <xref:System.String.ToLower%2A?displayProperty=nameWithType> is used in the call chain.

## Rule description

Use <xref:System.Convert.ToHexString%2A?displayProperty=nameWithType> or <xref:System.Convert.ToHexStringLower%2A?displayProperty=nameWithType> when encoding bytes to a hexadecimal string representation. These methods are more efficient and allocation-friendly than using <xref:System.BitConverter.ToString%2A?displayProperty=nameWithType> in combination with <xref:System.String.Replace%2A?displayProperty=nameWithType> to remove dashes and <xref:System.String.ToLower%2A?displayProperty=nameWithType>.

## How to fix violations

To fix a violation of this rule, replace the call chain with either <xref:System.Convert.ToHexString%2A?displayProperty=nameWithType> or <xref:System.Convert.ToHexStringLower%2A?displayProperty=nameWithType>.

## Example

The following code snippet shows a violation of CA1872:

```csharp
using System;
using System.Text;

class HelloWorldEncoder
{
private readonly byte[] _data = Encoding.ASCII.GetBytes("Hello World");

public string Encode()
{
return BitConverter.ToString(_data).Replace("-", "");
}

public string EncodeToLower()
{
return BitConverter.ToString(_data).Replace("-", "").ToLower();
}
}
```

```vb
Imports System
Imports System.Text

Class HelloWorldEncoder
Private ReadOnly _data As Byte() = Encoding.ASCII.GetBytes("Hello World")

Public Function Encode() As String
Return BitConverter.ToString(_data).Replace("-", "")
End Function

Public Function EncodeToLower() As String
Return BitConverter.ToString(_data).Replace("-", "").ToLower()
End Function
End Class
```

The following code snippet fixes the violation:

```csharp
using System;
using System.Text;

class HelloWorldEncoder
{
private readonly byte[] _data = Encoding.ASCII.GetBytes("Hello World");

public string Encode()
{
return Convert.ToHexString(data);
}

public string EncodeToLower()
{
return Convert.ToHexStringLower(data);
}
}
```

```vb
Imports System
Imports System.Text

Class HelloWorldEncoder
Private ReadOnly _data As Byte() = Encoding.ASCII.GetBytes("Hello World")

Public Function Encode() As String
Return Convert.ToHexString(data)
End Function

Public Function EncodeToLower() As String
Return Convert.ToHexStringLower(data)
End Function
End Class
```

## When to suppress warnings

It is safe to suppress a warning from this rule; however, we recommend that you use either <xref:System.Convert.ToHexString%2A?displayProperty=nameWithType> or <xref:System.Convert.ToHexStringLower%2A?displayProperty=nameWithType>.

## Suppress a warning

If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

```csharp
#pragma warning disable CA1872
// The code that's violating the rule is on this line.
#pragma warning restore CA1872
```

To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md).

```ini
[*.{cs,vb}]
dotnet_diagnostic.CA1872.severity = none
```

For more information, see [How to suppress code analysis warnings](../suppress-warnings.md).
1 change: 1 addition & 0 deletions docs/fundamentals/code-analysis/quality-rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ The following table lists code quality analysis rules.
> | [CA1868: Unnecessary call to 'Contains' for sets](ca1868.md) | Both <xref:System.Collections.Generic.ISet%601.Add(%600)?displayProperty=nameWithType> and <xref:System.Collections.Generic.ICollection%601.Remove(%600)?displayProperty=nameWithType> perform a lookup, which makes it redundant to call <xref:System.Collections.Generic.ICollection%601.Contains(%600)?displayProperty=nameWithType> beforehand. It's more efficient to call <xref:System.Collections.Generic.ISet%601.Add(%600)> or <xref:System.Collections.Generic.ICollection%601.Remove(%600)> directly, which returns a Boolean value indicating whether the item was added or removed. |
> | [CA1869: Cache and reuse 'JsonSerializerOptions' instances](ca1869.md) | Using a local instance of <xref:System.Text.Json.JsonSerializerOptions> for serialization or deserialization can substantially degrade the performance of your application if your code executes multiple times, since System.Text.Json internally caches serialization-related metadata into the provided instance. |
> | [CA1870: Use a cached 'SearchValues' instance](ca1870.md) | Using a cached <xref:System.Buffers.SearchValues%601> instance is more efficient than passing values to 'IndexOfAny' or 'ContainsAny' directly. |
> | [CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'](ca1872.md) | Use <xref:System.Convert.ToHexString%2A?displayProperty=nameWithType> or <xref:System.Convert.ToHexStringLower%2A?displayProperty=nameWithType> when encoding bytes to a hexadecimal string representation. These methods are more efficient and allocation-friendly than using <xref:System.BitConverter.ToString%2A?displayProperty=nameWithType> in combination with <xref:System.String.Replace%2A?displayProperty=nameWithType> to replace dashes and <xref:System.String.ToLower%2A?displayProperty=nameWithType>. |
> | [CA2000: Dispose objects before losing scope](ca2000.md) | Because an exceptional event might occur that will prevent the finalizer of an object from running, the object should be explicitly disposed before all references to it are out of scope. |
> | [CA2002: Do not lock on objects with weak identity](ca2002.md) |An object is said to have a weak identity when it can be directly accessed across application domain boundaries. A thread that tries to acquire a lock on an object that has a weak identity can be blocked by a second thread in a different application domain that has a lock on the same object. |
> | [CA2007: Do not directly await a Task](ca2007.md) | An asynchronous method [awaits](../../../csharp/language-reference/operators/await.md) a <xref:System.Threading.Tasks.Task> directly. When an asynchronous method awaits a <xref:System.Threading.Tasks.Task> directly, continuation occurs in the same thread that created the task. This behavior can be costly in terms of performance and can result in a deadlock on the UI thread. Consider calling <xref:System.Threading.Tasks.Task.ConfigureAwait(System.Boolean)?displayProperty=nameWithType> to signal your intention for continuation. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,4 @@ Performance rules support high-performance libraries and applications.
| [CA1868: Unnecessary call to 'Contains' for sets](ca1868.md) | Both <xref:System.Collections.Generic.ISet%601.Add(%600)?displayProperty=nameWithType> and <xref:System.Collections.Generic.ICollection%601.Remove(%600)?displayProperty=nameWithType> perform a lookup, which makes it redundant to call <xref:System.Collections.Generic.ICollection%601.Contains(%600)?displayProperty=nameWithType> beforehand. It's more efficient to call <xref:System.Collections.Generic.ISet%601.Add(%600)> or <xref:System.Collections.Generic.ICollection%601.Remove(%600)> directly, which returns a Boolean value indicating whether the item was added or removed. |
| [CA1869: Cache and reuse 'JsonSerializerOptions' instances](ca1869.md) | Using a local instance of <xref:System.Text.Json.JsonSerializerOptions> for serialization or deserialization can substantially degrade the performance of your application if your code executes multiple times, since System.Text.Json internally caches serialization-related metadata into the provided instance. |
| [CA1870: Use a cached 'SearchValues' instance](ca1870.md) | Using a cached <xref:System.Buffers.SearchValues%601> instance is more efficient than passing values to 'IndexOfAny' or 'ContainsAny' directly. |
| [CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'](ca1872.md) | Use <xref:System.Convert.ToHexString%2A?displayProperty=nameWithType> or <xref:System.Convert.ToHexStringLower%2A?displayProperty=nameWithType> when encoding bytes to a hexadecimal string representation. These methods are more efficient and allocation-friendly than using <xref:System.BitConverter.ToString%2A?displayProperty=nameWithType> in combination with <xref:System.String.Replace%2A?displayProperty=nameWithType> to replace dashes and <xref:System.String.ToLower%2A?displayProperty=nameWithType>. |
2 changes: 2 additions & 0 deletions docs/navigate/tools-diagnostics/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,8 @@ items:
href: ../../fundamentals/code-analysis/quality-rules/ca1869.md
- name: CA1870
href: ../../fundamentals/code-analysis/quality-rules/ca1870.md
- name: CA1872
href: ../../fundamentals/code-analysis/quality-rules/ca1872.md
- name: SingleFile rules
items:
- name: Overview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public override JsonConverter CreateConverter(
Type type,
JsonSerializerOptions options)
{
Type keyType = type.GetGenericArguments()[0];
Type valueType = type.GetGenericArguments()[1];
Type[] typeArguments = type.GetGenericArguments();
Type keyType = typeArguments[0];
Type valueType = typeArguments[1];

JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(DictionaryEnumConverterInner<,>).MakeGenericType(
Expand Down
Loading