* doc improvements

* feedback

* Update DE0001.md

* feedback

* brackets + minor edits

* Update PC002.md
This commit is contained in:
Maira Wenzel 2018-02-15 16:23:02 -08:00 коммит произвёл GitHub
Родитель 0b804783ec
Коммит 1b0c080300
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 125 добавлений и 80 удалений

Просмотреть файл

@ -6,26 +6,28 @@ T:System.Security.SecureString
## Motivation
* The purpose of `SecureString` is to avoid having secrets stored in the process
* The purpose of [`SecureString`][SecureString] is to avoid having secrets stored in the process
memory as plain text.
* However, even on Windows `SecureString` doesn't exist as an OS concept
- It just makes the window getting the plain text shorter; it doesn't fully
* However, even on Windows, [`SecureString`][SecureString] doesn't exist as an OS concept.
* It just makes the window getting the plain text shorter; it doesn't fully
prevent it as .NET still has to convert the string to a plain text
representation
- The benefit is that the plain text representation doesn't hang around
as an instance of `System.String` -- the lifetime of the native buffer is
representation.
* The benefit is that the plain text representation doesn't hang around
as an instance of [`System.String`][String] -- the lifetime of the native buffer is
shorter.
* The contents of the array is unencrypted except on .NET Framework.
- In .NET Framework, the contents of the internal char array is encrypted.
We've trouble with supporting the encryption in all environments, either
* In .NET Framework, the contents of the internal char array is encrypted.
.NET doesn't support encryption in all environments, either
due to missing APIs or key management issues.
## Recommendation
Don't use `SecureString` for new code. When porting code to .NET Core, consider
that the contents of the array will not be encrypted in memory.
Don't use [`SecureString`][SecureString] for new code. When porting code to .NET Core, consider
that the contents of the array are not encrypted in memory.
The general approach of dealing with credentials is to avoid them and instead
rely on other means to authenticate, such as certificates or Windows
authentication.
[SecureString]: https://docs.microsoft.com/dotnet/api/system.security.securestring
[String]: https://docs.microsoft.com/dotnet/api/system.string

Просмотреть файл

@ -6,7 +6,7 @@ N:System.Security.Permissions
## Motivation
When .NET Framework was originally it tried to provide a managed sandbox that
When .NET Framework was originally created, it tried to provide a managed sandbox that
allows restricting what parts of the process can do. Unfortunately, providing an
additional security boundary on top of the operating system has been proven to
be too difficult. As a result, there have been quite a few exploits that allows

Просмотреть файл

@ -9,9 +9,9 @@ T:System.Net.HttpWebRequest
## Motivation
`WebRequest`-based APIs are on life-support only (i.e. only critical fixes, no
`WebRequest`-based APIs are on life-support only (that is, only critical fixes, no
new improvements, enhancements).
## Recommendation
Use `HttpClient` instead.
Use [`HttpClient`](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient) instead.

Просмотреть файл

@ -6,9 +6,9 @@ T:System.Net.WebClient
## Motivation
`WebClient` is on life-support only (i.e. only critical fixes, no new
`WebClient` is on life-support only (that is, only critical fixes, no new
improvements, enhancements).
## Recommendation
Use `HttpClient` instead.
Use [`HttpClient`](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient) instead.

Просмотреть файл

@ -6,10 +6,9 @@ T:System.Net.Mail.SmtpClient
## Motivation
`SmtpClient` does not support many modern protocols. It is compat-only. It's
great for one off emails from tools, but does not scale to modern requirements
of the protocol.
[`SmtpClient`](https://docs.microsoft.com/dotnet/api/system.net.mail.smtpclient) doesn't support many modern protocols. It is compat-only. It's
great for one off emails from tools, but doesn't scale to modern requirements of the protocol.
## Recommendation
Use `MailKit` or other libraries.
Use [`MailKit`](https://github.com/jstedfast/MailKit) or other libraries.

Просмотреть файл

@ -18,38 +18,67 @@ T:System.Collections.CaseInsensitiveHashCodeProvider
## Motivation
When .NET was created, generic data types didn't exist, which is why the
collection types in `System.Collections` are untyped. However, since then
generic data types and thus a new set of collections in
`System.Collections.Generic` were made available.
collection types in the [`System.Collections`][collections] namespace are untyped. However, since then,
generic data types were introduced and thus a new set of collections
were made available in the [`System.Collections.Generic`][generic] and
[`System.Collections.ObjectModel`][objectmodel] namespaces.
## Recommendation
For new code, you shouldn't use non-generic collections:
* **Error prone**. Since non-generic collections are untyped, it requires frequent
* **Error prone**: since non-generic collections are untyped, it requires frequent
casting between `object` and the actual type you're expecting. Since the compiler
can't check that your types are consistent it's easer to put the wrong type in
can't check that your types are consistent, it's easier to put the wrong type in
the wrong collection.
* **Less performant**. Generic collection have the advantage that value types
* **Less performant**: generic collections have the advantage that value types
don't have to be boxed as object. For instance, a `List<int>` stores its data
in an `int[]`. That's far better than storing the data in `object[]` as that
requires boxing.
Consult the following table which how the non-generic collection types can be
replaced by their generic counterparts in `System.Collections.Generic`:
The following table shows how the non-generic collection types can be
replaced by their generic counterparts from the [`System.Collections.Generic`][generic] or
[`System.Collections.ObjectModel`][objectmodel] namespaces:
| Type | Replacement |
|-----------------------------------|------------------------------------------------------------|
| `ArrayList` | `List<T>` |
| `Hashtable` | `Dictionary<TKey, TValue>` |
| `Queue` | `Queue<T>` |
| `Stack` | `Stack<T>` |
| `SortedList` | `SortedList<TKey,TValue>` |
| `DictionaryEntry` | `KeyValuePair<TKey, TValue>` |
| `DictionaryBase` | `Dictionary<TKey, TValue> or KeyedCollection<TKey,TItem>` |
| `CollectionBase` | `Collection<T>` |
| `ReadOnlyCollectionBase` | `ReadOnlyCollection<T>` |
| `Comparer` | `Comparer<T>` |
| `CaseInsensitiveComparer` | `StringComparer.OrdinalIgnoreCase` |
| `CaseInsensitiveHashCodeProvider` | `StringComparer.OrdinalIgnoreCase` |
|----------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
| [`ArrayList`][arraylist] | [`List<T>`][list] |
| [`CaseInsensitiveComparer`][caseinsensitivecomparer] | [`StringComparer.OrdinalIgnoreCase`][ordinalignorecase] |
| [`CaseInsensitiveHashCodeProvider`][caseinsensitivehashcodeprovider] | [`StringComparer.OrdinalIgnoreCase`][ordinalignorecase] |
| [`CollectionBase`][collectionbase] | [`Collection<T>`][collection-1] |
| [`Comparer`][comparer] | [`Comparer<T>`][comparer-1] |
| [`DictionaryBase`][dictionarybase] | [`Dictionary<TKey, TValue>`][dictionary] or [`KeyedCollection<TKey,TItem>`][keyedcollection] |
| [`DictionaryEntry`][dictionaryentry] | [`KeyValuePair<TKey, TValue>`][keyvaluepair] |
| [`Hashtable`][hashtable] | [`Dictionary<TKey, TValue>`][dictionary] |
| [`Queue`][queue] | [`Queue<T>`][queue-1] |
| [`ReadOnlyCollectionBase`][readonlycollectionbase] | [`ReadOnlyCollection<T>`][readonlycollection] |
| [`SortedList`][sortedlist] | [`SortedList<TKey,TValue>`][sortedlist-2] |
| [`Stack`][stack] | [`Stack<T>`][stack-1] |
[arraylist]: https://docs.microsoft.com/dotnet/api/system.collections.arraylist
[caseinsensitivecomparer]: https://docs.microsoft.com/dotnet/api/system.collections.caseinsensitivecomparer
[caseinsensitivehashcodeprovider]: https://docs.microsoft.com/dotnet/api/system.collections.caseinsensitivehashcodeprovider
[collection-1]: https://docs.microsoft.com/dotnet/api/system.collections.objectmodel.collection-1
[collectionbase]: https://docs.microsoft.com/dotnet/api/system.collections.collectionbase
[collections]: https://docs.microsoft.com/dotnet/api/system.collections
[comparer]: https://docs.microsoft.com/dotnet/api/system.collections.comparer
[comparer-1]: https://docs.microsoft.com/dotnet/api/system.collections.generic.comparer-1
[dictionary]: https://docs.microsoft.com/dotnet/api/system.collections.generic.dictionary-2
[dictionarybase]: https://docs.microsoft.com/dotnet/api/system.collections.dictionarybase
[dictionaryentry]: https://docs.microsoft.com/dotnet/api/system.collections.dictionaryentry
[generic]: https://docs.microsoft.com/dotnet/api/system.collections.generic
[hashtable]: https://docs.microsoft.com/dotnet/api/system.collections.hashtable
[keyedcollection]: https://docs.microsoft.com/dotnet/api/system.collections.objectmodel.keyedcollection-2
[keyvaluepair]: https://docs.microsoft.com/dotnet/api/system.collections.generic.keyvaluepair-2
[list]: https://docs.microsoft.com/dotnet/api/system.collections.generic.list-1
[objectmodel]: https://docs.microsoft.com/dotnet/api/system.collections.objectmodel
[ordinalignorecase]: https://docs.microsoft.com/dotnet/api/system.stringcomparer.ordinalignorecase
[queue]: https://docs.microsoft.com/dotnet/api/system.collections.queue
[queue-1]: https://docs.microsoft.com/dotnet/api/system.collections.generic.queue-1
[readonlycollection]: https://docs.microsoft.com/dotnet/api/system.collections.objectmodel.readonlycollection-1
[readonlycollectionbase]: https://docs.microsoft.com/dotnet/api/system.collections.readonlycollectionbase
[stack]: https://docs.microsoft.com/dotnet/api/system.collections.stack
[stack-1]: https://docs.microsoft.com/dotnet/api/system.collections.generic.stack-1
[sortedlist]: https://docs.microsoft.com/dotnet/api/system.collections.sortedlist
[sortedlist-2]: https://docs.microsoft.com/dotnet/api/system.collections.generic.sortedlist-2

Просмотреть файл

@ -10,8 +10,8 @@ F:System.PlatformID.MacOSX
## Motivation
Certain enum values on `System.PlatformID` are no longer in use and will never
be returned from `Environment.OSVersion.Platform`.
Certain enum values on [`System.PlatformID`][PlatformID] are no longer in use and will never
be returned from [`Environment.OSVersion.Platform`][Platform].
## Recommendation
@ -24,8 +24,11 @@ the correct ones.
| Win32Windows | Unused
| WinCE | Unused
| Xbox | Unused
| MacOSX | Replaced. This value was only returned by Silverlight. On .NET Core, it will return `Unix`
| MacOSX | Replaced. This value was only returned by Silverlight. On .NET Core, it returns `Unix`.
Code that compares `Environment.OSVersion.Platform` to `PlatformID.MacOSX`
should use the newer `RuntimeInformation.IsOSPlatform(OSPlatform.OSX)` API
instead.
Code that compares [`Environment.OSVersion.Platform`][Platform] to [`PlatformID.MacOSX`][PlatformID]
should use the newer [`RuntimeInformation.IsOSPlatform(OSPlatform.OSX)`][IsOSPlatform] method instead.
[IsOSPlatform]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.runtimeinformation.isosplatform
[Platform]: https://docs.microsoft.com/dotnet/api/system.operatingsystem.platform
[PlatformID]: https://docs.microsoft.com/dotnet/api/system.platformid

Просмотреть файл

@ -9,13 +9,17 @@ M:System.Threading.Thread.set_CurrentUICulture(System.Globalization.CultureInfo)
## Motivation
These properties don't work consistently across operating systems and runtimes when used against
Thread culture properties don't work consistently across operating systems and runtimes when used against
any thread other than the current thread.
* In .NET Core, an `InvalidOperationException` is thrown if a thread tries
to read or write these properties on a different thread.
* In .NET Core, if a thread tries to read or write these properties on a different thread, an [`InvalidOperationException`][InvalidOperationException] is thrown.
* In .NET Framework, setting these properties isn't reliable for a different thread.
## Recommendation
Use `CultureInfo.CurrentCulture` and `CultureInfo.CurrentUICulture` instead.
Use [`CultureInfo.CurrentCulture`][CurrentCulture] and [`CultureInfo.CurrentUICulture`][CurrentUICulture] instead.
[CurrentCulture]: https://docs.microsoft.com/dotnet/api/system.globalization.cultureinfo.currentculture
[CurrentUICulture]: https://docs.microsoft.com/dotnet/api/system.globalization.cultureinfo.currentuiculture
[InvalidOperationException]: https://docs.microsoft.com/dotnet/api/system.invalidoperationexception

Просмотреть файл

@ -2,30 +2,30 @@
## Cause
You're calling an API in .NET Core or .NET Standard that will throw
`PlatformNotSupportedException` in all or some circumstances.
You're calling an API in .NET Core or .NET Standard that throws
[`PlatformNotSupportedException`][PlatformNotSupportedException] in all or some circumstances.
## Rule Description
## Rule description
The goal of this rule is assisting you in writing robust code that will work
across all platforms that your code might run on.
## How to Fix Violations
## How to fix violations
The analyzer has no way to detect whether your code is correctly guarded against
`PlatformNotSupportedException`. The fix is to review the API documentation for
which this rule was triggered for and to do one of the following:
[`PlatformNotSupportedException`][PlatformNotSupportedException]. The fix is to review the API documentation for
which this rule was triggered and to do one of the following:
1. Not calling the API
2. Guard this call and suppress the specific occurrence of this rule
3. Not running your code on the affected platforms and suppressing this rule for
said platforms
1. Not call the API.
2. Guard this call and suppress the specific occurrence of this rule.
3. Not run your code on the affected platforms and suppress this rule for
said platforms.
## When to Suppress Warnings
## When to suppress warnings
Unless you stop calling the API entirely, you'll have to suppress this warning.
Unless you stop calling the API entirely, you have to suppress this warning.
If you want to suppress a specific occurrence, use `#pragma warning disable`:
If you want to suppress a specific occurrence, use `#pragma warning disable` as shown in the following example:
```C#
#pragma warning disable PC001 // API not supported on all platforms
@ -34,11 +34,19 @@ If you want to suppress a specific occurrence, use `#pragma warning disable`:
```
If you want to ignore certain platforms, you need to edit your project file and
add a property `PlatformCompatIgnore` that lists all platforms you don't plan to
run your code on:
add a `PlatformCompatIgnore` property that lists all platforms you don't plan to
run your code on like in the following example:
```XML
<PropertyGroup>
<PlatformCompatIgnore>Linux;MacOSX</PlatformCompatIgnore>
</PropertyGroup>
```
The `PlatformCompatIgnore` property accepts the following values:
* Linux
* macOS
* Windows
[PlatformNotSupportedException]: https://docs.microsoft.com/dotnet/api/system.platformnotsupportedexception

Просмотреть файл

@ -2,26 +2,26 @@
## Cause
You're calling an API in .NET Standard that isn't available in .NET Framework
You're calling an API in .NET Standard that isn't available in the .NET Framework
4.6.1.
## Rule Description
## Rule description
While .NET Framework 4.6.1 is treated by NuGet as implementing .NET Standard
2.0, it doesn't fully implement it. This was trade-off that is explained in the
documentation of [.NET Standard][netfx-netstandard].
While the .NET Framework 4.6.1 is treated by NuGet as implementing .NET Standard
2.0, it doesn't fully implement it. This trade-off is explained in the
[.NET Standard][netfx-netstandard] specification.
## How to Fix Violations
## How to fix violations
You cannot reasonably guard your code against missing APIs. You only have two
options:
1. Not calling the affected API
2. Not running your code on .NET Framework 4.6.1
1. Not call the affected API.
2. Not run your code on .NET Framework 4.6.1.
## When to Suppress Warnings
## When to suppress warnings
Unless you stop calling the API entirely, you'll have to suppress this warning:
Unless you stop calling the API entirely, you have to suppress this warning as shown in the following example:
```C#
using System.Diagnostics.CodeAnalysis;

Просмотреть файл

@ -5,18 +5,18 @@
You're P/Invoking into a native API from a .NET Standard project or a UWP
project but that API isn't available in UWP.
## Rule Description
## Rule description
Not all Win32 APIs are available in UWP. While calling the API might work when
debugging the app, the app store will reject any apps that contain P/Invoke
declarations with unsupported APIs.
## How to Fix Violations
## How to fix violations
Remove the P/Invoke declaration. When targeting .NET Standard, consider cross-
targeting for UWP.
## When to Suppress Warnings
## When to suppress warnings
The tool might not be able to detect usages of APIs that part of your
application. If it's a native module that you deploy with your app, you should