Skip to content

Commit 7bcec4c

Browse files
authored
Merge pull request #5734 from MicrosoftDocs/master637329588922878660
For protected CLA branch, push strategy should use PR and merge to target branch method to work around git push error
2 parents 69a6e93 + 8d9bd4a commit 7bcec4c

11 files changed

+234
-49
lines changed

docs/code-quality/ca1838.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
title: "CA1838: Avoid StringBuilder parameters for P/Invokes"
3+
ms.date: 08/03/2020
4+
ms.topic: reference
5+
f1_keywords:
6+
- "AvoidStringBuilderPInvokeParameters"
7+
- "CA1838"
8+
helpviewer_keywords:
9+
- "AvoidStringBuilderPInvokeParameters"
10+
- "CA1838"
11+
author: elinor-fung
12+
ms.author: elfung
13+
manager: jeffschw
14+
ms.workload:
15+
- "multiple"
16+
---
17+
18+
# CA1838: Avoid `StringBuilder` parameters for P/Invokes
19+
20+
|Item|Value|
21+
|-|-|
22+
|CheckId|CA1838|
23+
|Category|Microsoft.Performance|
24+
|Breaking change|Non-breaking|
25+
26+
## Cause
27+
28+
A [P/Invoke](/dotnet/standard/native-interop/pinvoke) has a <xref:System.Text.StringBuilder> parameter.
29+
30+
## Rule description
31+
32+
Marshaling of `StringBuilder` always creates a native buffer copy, resulting in multiple allocations for one P/Invoke call. To marshal a `StringBuilder` as a P/Invoke parameter, the runtime will:
33+
- Allocate a native buffer
34+
- If it is an `In` parameter, copy the contents of the `StringBuilder` to the native buffer
35+
- If it is an `Out` parameter, copy the native buffer into a newly allocated managed array
36+
37+
By default, `StringBuilder` is `In` and `Out`.
38+
39+
This rule is disabled by default, because it can require case-by-case analysis of whether the violation is of interest and potentially non-trivial refactoring to address the violation. Users can explicitly enable this rule by configuring the [severity of analyzer rules](use-roslyn-analyzers.md#rule-severity).
40+
41+
## How to fix violations
42+
43+
In general, addressing a violation involves reworking the P/Invoke and its callers to use a buffer instead of `StringBuilder`. The specifics would depend on the use cases for the P/Invoke.
44+
45+
Here is an example for the common scenario of using `StringBuilder` as an output buffer to be filled by the native function:
46+
47+
```csharp
48+
// Violation
49+
[DllImport("MyLibrary", CharSet = CharSet.Unicode)]
50+
private static extern void Foo(StringBuilder sb, ref int length);
51+
52+
public void Bar()
53+
{
54+
int BufferSize = ...
55+
StringBuilder sb = new StringBuilder(BufferSize);
56+
int len = sb.Capacity;
57+
Foo(sb, ref len);
58+
string result = sb.ToString();
59+
}
60+
```
61+
62+
For use cases where the buffer is small and `unsafe` code is acceptable, [stackalloc](/dotnet/csharp/language-reference/operators/stackalloc) can be used to allocate the buffer on the stack:
63+
64+
```csharp
65+
[DllImport("MyLibrary", CharSet = CharSet.Unicode)]
66+
private static extern unsafe void Foo(char* buffer, ref int length);
67+
68+
public void Bar()
69+
{
70+
int BufferSize = ...
71+
unsafe
72+
{
73+
char* buffer = stackalloc char[BufferSize];
74+
int len = BufferSize;
75+
Foo(buffer, ref len);
76+
string result = new string(buffer);
77+
}
78+
}
79+
```
80+
81+
For larger buffers, a new array can be allocated as the buffer:
82+
83+
```csharp
84+
[DllImport("MyLibrary", CharSet = CharSet.Unicode)]
85+
private static extern void Foo([Out] char[] buffer, ref int length);
86+
87+
public void Bar()
88+
{
89+
int BufferSize = ...
90+
char[] buffer = new char[BufferSize];
91+
int len = buffer.Length;
92+
Foo(buffer, ref len);
93+
string result = new string(buffer);
94+
}
95+
```
96+
97+
When the P/Invoke is frequently called for larger buffers, <xref:System.Buffers.ArrayPool%601> can be used to avoid the repeated allocations and memory pressure that comes with them:
98+
99+
```csharp
100+
[DllImport("MyLibrary", CharSet = CharSet.Unicode)]
101+
private static extern unsafe void Foo([Out] char[] buffer, ref int length);
102+
103+
public void Bar()
104+
{
105+
int BufferSize = ...
106+
char[] buffer = ArrayPool<char>.Shared.Rent(BufferSize);
107+
try
108+
{
109+
int len = buffer.Length;
110+
Foo(buffer, ref len);
111+
string result = new string(buffer);
112+
}
113+
finally
114+
{
115+
ArrayPool<char>.Shared.Return(buffer);
116+
}
117+
}
118+
```
119+
120+
If the buffer size is not known until runtime, the buffer may need to be created differently based on the size to avoid allocating large buffers with `stackalloc`.
121+
122+
The preceding examples use 2-byte wide characters (`CharSet.Unicode`). If the native function uses 1-byte characters (`CharSet.Ansi`), a `byte` buffer can be used instead of a `char` buffer. For example:
123+
124+
```csharp
125+
[DllImport("MyLibrary", CharSet = CharSet.Ansi)]
126+
private static extern unsafe void Foo(byte* buffer, ref int length);
127+
128+
public void Bar()
129+
{
130+
int BufferSize = ...
131+
unsafe
132+
{
133+
byte* buffer = stackalloc byte[BufferSize];
134+
int len = BufferSize;
135+
Foo(buffer, ref len);
136+
string result = Marshal.PtrToStringAnsi((IntPtr)buffer);
137+
}
138+
}
139+
```
140+
141+
If the parameter is also used as input, the buffers need to be populated with the string data with any null terminator explicitly added.
142+
143+
## When to suppress warnings
144+
145+
Suppress a violation of this rule if you're not concerned about the performance impact of marshaling a `StringBuilder`.
146+
147+
## See also
148+
149+
- [Performance warnings](../code-quality/performance-warnings.md)
150+
- [Native interoperability best practices](/dotnet/standard/native-interop/best-practices)
151+
- <xref:System.Buffers.ArrayPool%601>
152+
- [stackalloc](/dotnet/csharp/language-reference/operators/stackalloc)
153+
- [Charsets](/dotnet/standard/native-interop/charset)

docs/code-quality/code-analysis-warnings-for-managed-code-by-checkid.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ f1_keywords:
173173
- CA1833
174174
- CA1835
175175
- CA1836
176+
- CA1838
176177
- CA1900
177178
- CA1901
178179
- CA1903
@@ -459,6 +460,7 @@ The following table lists Code Analysis warnings for managed code by the CheckId
459460
| CA1833 |[CA1833: Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array](../code-quality/ca1833.md) | When using a range-indexer on an array and implicitly assigning the value to a <xref:System.Span%601> or <xref:System.Memory%601> type, the method <xref:System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray%2A> will be used instead of <xref:System.Span%601.Slice%2A?#System_Span_1_Slice_System_Int32_System_Int32_>, which produces a copy of requested portion of the array. |
460461
| CA1835 |[CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'](../code-quality/ca1835.md) | 'Stream' has a 'ReadAsync' overload that takes a 'Memory&lt;Byte&gt;' as the first argument, and a 'WriteAsync' overload that takes a 'ReadOnlyMemory&lt;Byte&gt;' as the first argument. Prefer calling the memory based overloads, which are more efficient. |
461462
| CA1836 |[CA1836: Prefer `IsEmpty` over `Count` when available](../code-quality/ca1836.md) | Prefer `IsEmpty` property that is more efficient than `Count`, `Length`, <xref:System.Linq.Enumerable.Count%60%601%28System.Collections.Generic.IEnumerable%7B%60%600%7D%29> or <xref:System.Linq.Enumerable.LongCount%60%601%28System.Collections.Generic.IEnumerable%7B%60%600%7D%29> to determine whether the object contains or not any items. |
463+
| CA1838 | [CA1838: Avoid `StringBuilder` parameters for P/Invokes](../code-quality/ca1838.md) | Marshaling of 'StringBuilder' always creates a native buffer copy, resulting in multiple allocations for one marshaling operation. |
462464
| CA1900 | [CA1900: Value type fields should be portable](../code-quality/ca1900.md) | This rule checks that structures that are declared by using explicit layout will align correctly when marshaled to unmanaged code on 64-bit operating systems. |
463465
| CA1901 | [CA1901: P/Invoke declarations should be portable](../code-quality/ca1901.md) | This rule evaluates the size of each parameter and the return value of a P/Invoke, and verifies that the size of the parameter is correct when marshaled to unmanaged code on 32-bit and 64-bit operating systems. |
464466
| CA1903 | [CA1903: Use only API from targeted framework](../code-quality/ca1903.md) | A member or type is using a member or type that was introduced in a service pack that was not included together with the targeted framework of the project. |

docs/code-quality/performance-warnings.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ Performance warnings support high-performance libraries and applications.
5454
| [CA1833: Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array](../code-quality/ca1833.md) | When using a range-indexer on an array and implicitly assigning the value to a <xref:System.Span%601> or <xref:System.Memory%601> type, the method <xref:System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray%2A> will be used instead of <xref:System.Span%601.Slice%2A?#System_Span_1_Slice_System_Int32_System_Int32_>, which produces a copy of requested portion of the array. |
5555
| [CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'](../code-quality/ca1835.md) | 'Stream' has a 'ReadAsync' overload that takes a 'Memory&lt;Byte&gt;' as the first argument, and a 'WriteAsync' overload that takes a 'ReadOnlyMemory&lt;Byte&gt;' as the first argument. Prefer calling the memory based overloads, which are more efficient. |
5656
| [CA1836: Prefer `IsEmpty` over `Count` when available](../code-quality/ca1836.md) | Prefer `IsEmpty` property that is more efficient than `Count`, `Length`, <xref:System.Linq.Enumerable.Count%60%601%28System.Collections.Generic.IEnumerable%7B%60%600%7D%29> or <xref:System.Linq.Enumerable.LongCount%60%601%28System.Collections.Generic.IEnumerable%7B%60%600%7D%29> to determine whether the object contains or not any items. |
57+
| [CA1838: Avoid `StringBuilder` parameters for P/Invokes](../code-quality/ca1838.md) | Marshaling of 'StringBuilder' always creates a native buffer copy, resulting in multiple allocations for one marshaling operation. |

docs/code-quality/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@
567567
href: ca1835.md
568568
- name: "CA1836: Prefer IsEmpty over Count when available"
569569
href: ca1836.md
570+
- name: "CA1838: Avoid StringBuilder parameters for P/Invokes"
571+
href: ca1838.md
570572
- name: Portability warnings
571573
items:
572574
- name: Overview
Loading
Loading

docs/ide/reference/options-text-editor-basic-visual-basic.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Options, Text Editor, Basic (VB), Advanced
3-
ms.date: 01/16/2019
3+
ms.date: 08/12/2020
44
ms.topic: reference
55
f1_keywords:
66
- VS.ToolsOptionsPages.Visual_Basic.Editor
@@ -13,8 +13,8 @@ f1_keywords:
1313
helpviewer_keywords:
1414
- Basic Text Editor Options dialog box
1515
ms.assetid: 5a8cafca-f7b4-4a2d-92ce-6894a7673d00
16-
author: TerryGLee
17-
ms.author: tglee
16+
author: akhera99
17+
ms.author: midumont
1818
manager: jillfra
1919
ms.workload:
2020
- multiple
@@ -73,6 +73,13 @@ When selected, vertical lines appear in the editor that line up with structured
7373

7474
## Editor Help
7575

76+
::: moniker range=">=vs-2019"
77+
**Inline Parameter Name Hints**
78+
When selected, inserts parameter name hints for literals, casted literals, and object instantiations prior to each argument in function calls.
79+
80+
![Inline Parameter Name Hints for Visual Basic](media/inline-parameter-name-hints-visualbasic.png)
81+
::: moniker-end
82+
7683
**Pretty Listing (reformatting) of code**
7784
The text editor reformats your code as appropriate. When this option is selected, the code editor will:
7885

docs/ide/reference/options-text-editor-csharp-advanced.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
22
title: Options, Text Editor, C#, Advanced
3-
ms.date: 01/16/2019
3+
ms.date: 08/12/2020
44
ms.topic: reference
55
f1_keywords:
66
- VS.ToolsOptionsPages.Text_Editor.CSharp.Outlining
77
- VS.ToolsOptionsPages.Text_Editor.CSharp.Advanced
8-
author: TerryGLee
9-
ms.author: tglee
8+
author: akhera99
9+
ms.author: midumont
1010
manager: jillfra
1111
ms.workload:
1212
- dotnet
@@ -122,7 +122,13 @@ Use the **Advanced** options page to modify the settings for editor formatting,
122122
Select these check boxes to display dotted vertical lines between the curly brackets (**{}**) in your code. You can then easily see individual blocks of code for your declaration level and code level constructs.
123123

124124
## Editor Help
125-
125+
::: moniker range=">=vs-2019"
126+
- Inline Parameter Name Hints
127+
128+
When selected, inserts parameter name hints for literals, casted literals, and object instantiations prior to each argument in function calls.
129+
130+
![Inline Parameter Name Hints for CSharp](media/inline-parameter-name-hints-csharp.png)
131+
::: moniker-end
126132
- Generate XML documentation comments for ///
127133

128134
When selected, inserts the XML elements for XML documentation comments after you type the `///` comment introduction. For more information about XML documentation, see [XML Documentation Comments (C# Programming Guide)](/dotnet/csharp/programming-guide/xmldoc/xml-documentation-comments).

docs/ide/visual-studio-performance-tips-and-tricks.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Tips to improve performance
3-
ms.date: 08/14/2018
3+
ms.date: 08/13/2020
44
ms.topic: conceptual
55
author: TerryGLee
66
ms.author: tglee
@@ -111,11 +111,25 @@ For information about .NET Compiler Platform ("Roslyn") performance consideratio
111111

112112
::: moniker-end
113113

114+
- **Disable map mode**
115+
116+
[**Map mode**](how-to-track-your-code-by-customizing-the-scrollbar.md#display-modes) displays lines of code, in miniature, on the scroll bar. Map mode is enabled by default.
117+
118+
To disable map mode, go to **Tools** > **Options** > **Text Editor** > **All Languages** > **Scroll Bars**, and in the **Behavior** section, deselect the **Use map mode for vertical scroll bar** option.
119+
120+
- **Disable word wrap**
121+
122+
[**Word wrap**](./reference/how-to-manage-word-wrap-in-the-editor.md) displays the portion of a long line of code that extends beyond the current width of the code editor window. Word wrap is on by default.
123+
124+
To disable word wrap for a project that you are currently working on, go to **Edit** > **Advanced** > **Word Wrap**. (You can toggle this setting by using the same menu commands.)
125+
126+
To disable word wrap for all projects, go to **Tools** > **Options** > **General** > **Text Editor** > **All Languages** > **General**, and in the **Settings** section, deselect the **Word wrap** option.
127+
114128
- **Disable XAML Designer**
115129

116130
The XAML designer is enabled by default, but only consumes resources if you open a *.xaml* file. If you work with XAML files but do not wish to use the designer functionality, disable this feature to free up some memory.
117131

118-
To disable **XAML Designer**, go to **Tools** > **Options** > **XAML Designer** > **Enable XAML Designer**, and deselect the option.
132+
To disable XAML Designer, go to **Tools** > **Options** > **XAML Designer** > **Enable XAML Designer**, and deselect the option.
119133

120134
- **Remove workloads**
121135

0 commit comments

Comments
 (0)