Skip to content

Commit

Permalink
Merge pull request #40196 from dotnet/main
Browse files Browse the repository at this point in the history
  • Loading branch information
BillWagner committed Mar 25, 2024
2 parents a51aa85 + 17b2f90 commit 431c357
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 5 deletions.
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

0 comments on commit 431c357

Please sign in to comment.