Remove langcode from MSDN links

YoshiRulz 2025-05-23 03:16:32 +10:00
parent cdd4703eb2
commit e39f8ab984
1 changed files with 20 additions and 20 deletions

@ -9,26 +9,26 @@ Under .NET 8 (all of this is untested, just based on the docs and .NET issue tra
- The largest 1D byte array is `new byte[Array.MaxLength]`, `Array.MaxLength` being [hardcoded to `0x7FFF_FFC7`](https://github.com/dotnet/runtime/blob/5535e31a712343a63f5d7d796cd874e563e5ac14/src/libraries/System.Private.CoreLib/src/System/Array.cs#L2135-L2137) or just under 2 GiB. (Would probably want to alloc in 1 GiB chunks to have nice code, maybe even smaller to keep the GC happy.) - The largest 1D byte array is `new byte[Array.MaxLength]`, `Array.MaxLength` being [hardcoded to `0x7FFF_FFC7`](https://github.com/dotnet/runtime/blob/5535e31a712343a63f5d7d796cd874e563e5ac14/src/libraries/System.Private.CoreLib/src/System/Array.cs#L2135-L2137) or just under 2 GiB. (Would probably want to alloc in 1 GiB chunks to have nice code, maybe even smaller to keep the GC happy.)
- The largest 1D struct array is `new T[Array.MaxLength]`. So its size is... unbounded since structs don't have a size limit apart from the stack size (and `[InlineArray]`'s poorly-documented 1 MiB cap). (TODO check there isn't an undocumented cap on struct size) - The largest 1D struct array is `new T[Array.MaxLength]`. So its size is... unbounded since structs don't have a size limit apart from the stack size (and `[InlineArray]`'s poorly-documented 1 MiB cap). (TODO check there isn't an undocumented cap on struct size)
- The largest *n*-D byte array is `UNK()` (`LongLength` is `0xUNK` or UNK GiB). - The largest *n*-D byte array is `UNK()` (`LongLength` is `0xUNK` or UNK GiB).
- If a call would allocate beyond those limits (or the process' or machine's limits), an `OutOfMemoryException` will be thrown, which can be caught and handled [but definitely shouldn't be](https://learn.microsoft.com/en-us/dotnet/api/system.outofmemoryexception?view=net-8.0#remarks). - If a call would allocate beyond those limits (or the process' or machine's limits), an `OutOfMemoryException` will be thrown, which can be caught and handled [but definitely shouldn't be](https://learn.microsoft.com/dotnet/api/system.outofmemoryexception?view=net-8.0#remarks).
- All of that is on the managed heap. The default/global stack is OS-specific and [cannot be changed](https://github.com/dotnet/runtime/issues/107183): On Windows, it's 1.5 MiB [due to an oversight](https://github.com/dotnet/runtime/issues/96347#issuecomment-1871528297), and on Linux, it's inherited from the OS, [typically 8 MiB](https://github.com/dotnet/runtime/issues/33622#issuecomment-599462300). - All of that is on the managed heap. The default/global stack is OS-specific and [cannot be changed](https://github.com/dotnet/runtime/issues/107183): On Windows, it's 1.5 MiB [due to an oversight](https://github.com/dotnet/runtime/issues/96347#issuecomment-1871528297), and on Linux, it's inherited from the OS, [typically 8 MiB](https://github.com/dotnet/runtime/issues/33622#issuecomment-599462300).
- The stack size for managed threads can be [specified on init](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.-ctor?view=net-8.0#system-threading-thread-ctor(system-threading-threadstart-system-int32)), though as with all of this you may have an XY problem and should reconsider. - The stack size for managed threads can be [specified on init](https://learn.microsoft.com/dotnet/api/system.threading.thread.-ctor?view=net-8.0#system-threading-thread-ctor(system-threading-threadstart-system-int32)), though as with all of this you may have an XY problem and should reconsider.
- If a call would allocate beyond the stack size (or a call chain grows out of control), a `StackOverflowException` will be thrown, which [cannot be caught](https://learn.microsoft.com/en-us/dotnet/api/system.stackoverflowexception?view=net-8.0#remarks). - If a call would allocate beyond the stack size (or a call chain grows out of control), a `StackOverflowException` will be thrown, which [cannot be caught](https://learn.microsoft.com/dotnet/api/system.stackoverflowexception?view=net-8.0#remarks).
Under Mono (x64 unless specified and without `gcAllowVeryLargeObjects`, TODO see if Mono respects that): Under Mono (x64 unless specified and without `gcAllowVeryLargeObjects`, TODO see if Mono respects that):
- The largest 1D byte array is `new byte[int.MaxValue]` (just under 2 GiB), as there is no way to instantiate an array with a larger size (`Array.CreateInstance(typeof(T), 0x8000_0000L)` will throw `ArgumentOutOfRangeException: Arrays larger than 2GB are not supported.`, which I suppose is technically incorrect). - The largest 1D byte array is `new byte[int.MaxValue]` (just under 2 GiB), as there is no way to instantiate an array with a larger size (`Array.CreateInstance(typeof(T), 0x8000_0000L)` will throw `ArgumentOutOfRangeException: Arrays larger than 2GB are not supported.`, which I suppose is technically incorrect).
- Similarly, the largest 1D struct array is `new T[int.MaxValue]`. So its size is... unbounded since structs on the heap don't have a size limit. - Similarly, the largest 1D struct array is `new T[int.MaxValue]`. So its size is... unbounded since structs on the heap don't have a size limit.
- The largest *n*-D byte array is `new byte[2, 0x7FFF_FFE6]` (`LongLength` is `0xFFFF_FFCC` or just under 4 GiB). Allocating a single byte more gives an OoME. Multidimensional arrays of other structs appear to also be limited to `0xFFFF_FFCC` octets. - The largest *n*-D byte array is `new byte[2, 0x7FFF_FFE6]` (`LongLength` is `0xFFFF_FFCC` or just under 4 GiB). Allocating a single byte more gives an OoME. Multidimensional arrays of other structs appear to also be limited to `0xFFFF_FFCC` octets.
- If a call would allocate beyond those limits (or the process' or machine's limits), the relevant builtin method will throw an `OutOfMemoryException`, which can be caught and handled [but definitely shouldn't be](https://learn.microsoft.com/en-us/dotnet/api/system.outofmemoryexception?view=netframework-4.8#remarks). - If a call would allocate beyond those limits (or the process' or machine's limits), the relevant builtin method will throw an `OutOfMemoryException`, which can be caught and handled [but definitely shouldn't be](https://learn.microsoft.com/dotnet/api/system.outofmemoryexception?view=netframework-4.8#remarks).
- All of that is on the managed heap. The default/global stack is UNK MiB large and can be changed [externally with `ulimit`](https://github.com/dotnet/runtime/issues/96347#issuecomment-1981511546) (a builtin in most POSIX shells, including BASH), but not with Roslyn. - All of that is on the managed heap. The default/global stack is UNK MiB large and can be changed [externally with `ulimit`](https://github.com/dotnet/runtime/issues/96347#issuecomment-1981511546) (a builtin in most POSIX shells, including BASH), but not with Roslyn.
- The stack size for managed threads can be [specified on init](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.-ctor?view=netframework-4.8#system-threading-thread-ctor(system-threading-threadstart-system-int32)), though as with all of this you may have an XY problem and should reconsider. The max. is [1 MiB / 2 MiB (32-bit/64-bit hosts)](https://stackoverflow.com/a/19909421), and there is a [hack to bypass the limit](https://stackoverflow.com/a/48003390) (untested). - The stack size for managed threads can be [specified on init](https://learn.microsoft.com/dotnet/api/system.threading.thread.-ctor?view=netframework-4.8#system-threading-thread-ctor(system-threading-threadstart-system-int32)), though as with all of this you may have an XY problem and should reconsider. The max. is [1 MiB / 2 MiB (32-bit/64-bit hosts)](https://stackoverflow.com/a/19909421), and there is a [hack to bypass the limit](https://stackoverflow.com/a/48003390) (untested).
- If a `stackalloc` call would allocate beyond those limits (with `stackalloc`; TODO check this), or a call chain grows out of control, a `StackOverflowException` will be thrown, which [cannot be caught](https://learn.microsoft.com/en-us/dotnet/api/system.stackoverflowexception?view=netframework-4.8#remarks). - If a `stackalloc` call would allocate beyond those limits (with `stackalloc`; TODO check this), or a call chain grows out of control, a `StackOverflowException` will be thrown, which [cannot be caught](https://learn.microsoft.com/dotnet/api/system.stackoverflowexception?view=netframework-4.8#remarks).
Under .NET Framework on Windows (x64 unless specified): Under .NET Framework on Windows (x64 unless specified):
- Untested, but I'm guessing it's probably the same as Mono so long as the [`gcAllowVeryLargeObjects`](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/gcallowverylargeobjects-element) is enabled in the runtime config, going by those docs and [this blog post](https://www.centerspace.net/large-matrices-and-vectors). - Untested, but I'm guessing it's probably the same as Mono so long as the [`gcAllowVeryLargeObjects`](https://learn.microsoft.com/dotnet/framework/configure-apps/file-schema/runtime/gcallowverylargeobjects-element) is enabled in the runtime config, going by those docs and [this blog post](https://www.centerspace.net/large-matrices-and-vectors).
- Or maybe not; see [this SO answer](https://stackoverflow.com/a/34413257) and the comment below it. - Or maybe not; see [this SO answer](https://stackoverflow.com/a/34413257) and the comment below it.
- The default/global stack is 1 MiB, specified in a PE header. This can be changed [externally with `EDITBIN`](https://stackoverflow.com/a/54584830), but not with Roslyn nor at runtime in any way. - The default/global stack is 1 MiB, specified in a PE header. This can be changed [externally with `EDITBIN`](https://stackoverflow.com/a/54584830), but not with Roslyn nor at runtime in any way.
- The stack size for managed threads [defaults to 1 MiB / 4 MiB (x86/x64)](https://stackoverflow.com/a/5507910) (TODO surely there's an official source) can be [specified on init](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.-ctor?view=netframework-4.8#system-threading-thread-ctor(system-threading-threadstart-system-int32)), though as with all of this you may have an XY problem and should reconsider. The max. is UNK MiB (default AppDomain; 1 MiB if untrusted) and the min. [seems to be OS-dependent](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.-ctor?view=netframework-4.8#system-threading-thread-ctor(system-threading-threadstart-system-int32)) but was [~256 KiB on Vista](https://techcommunity.microsoft.com/t5/windows-blog-archive/pushing-the-limits-of-windows-processes-and-threads/ba-p/723824) and presumably hasn't been changed since. - The stack size for managed threads [defaults to 1 MiB / 4 MiB (x86/x64)](https://stackoverflow.com/a/5507910) (TODO surely there's an official source) can be [specified on init](https://learn.microsoft.com/dotnet/api/system.threading.thread.-ctor?view=netframework-4.8#system-threading-thread-ctor(system-threading-threadstart-system-int32)), though as with all of this you may have an XY problem and should reconsider. The max. is UNK MiB (default AppDomain; 1 MiB if untrusted) and the min. [seems to be OS-dependent](https://learn.microsoft.com/dotnet/api/system.threading.thread.-ctor?view=netframework-4.8#system-threading-thread-ctor(system-threading-threadstart-system-int32)) but was [~256 KiB on Vista](https://techcommunity.microsoft.com/t5/windows-blog-archive/pushing-the-limits-of-windows-processes-and-threads/ba-p/723824) and presumably hasn't been changed since.
- If a call would allocate beyond the stack size (or a call chain grows out of control), a `StackOverflowException` will be thrown, which [cannot be caught](https://learn.microsoft.com/en-us/dotnet/api/system.stackoverflowexception?view=netframework-4.8#remarks). - If a call would allocate beyond the stack size (or a call chain grows out of control), a `StackOverflowException` will be thrown, which [cannot be caught](https://learn.microsoft.com/dotnet/api/system.stackoverflowexception?view=netframework-4.8#remarks).
- It should be no surprise that all these limits were inherited from native Win32. Thankfully modern .NET is deviating from that where necessary. - It should be no surprise that all these limits were inherited from native Win32. Thankfully modern .NET is deviating from that where necessary.
## BCL source ## BCL source
@ -41,18 +41,18 @@ The API reference on Microsoft Learn (formerly MSDN) now links to the source in
## Const (byte/primitive) arrays ## Const (byte/primitive) arrays
Not allowed as either array nor `Span`, despite string literals now effectively having the type `const ReadOnlySpan<char>`, Not allowed as either array nor `Span`, despite string literals now effectively having the type `const ReadOnlySpan<char>`,
and despite arrays of primitive types being [allowed for attribute parameters](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/reflection-and-attributes/attribute-tutorial#add-attributes-to-code) since forever. and despite arrays of primitive types being [allowed for attribute parameters](https://learn.microsoft.com/dotnet/csharp/advanced-topics/reflection-and-attributes/attribute-tutorial#add-attributes-to-code) since forever.
Use `static readonly` and weep. Use `static readonly` and weep.
## Const structs ## Const structs
Not allowed, even if they meet the [criteria for unmanaged types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/unmanaged-types) and are littered with [explicit layout attributes](https://learn.microsoft.com/en-us/dotnet/standard/native-interop/customize-struct-marshalling). Not allowed, even if they meet the [criteria for unmanaged types](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/unmanaged-types) and are littered with [explicit layout attributes](https://learn.microsoft.com/dotnet/standard/native-interop/customize-struct-marshalling).
First-class'd structs are no different, so fields of type `ValueTuple`, `Range`, and as noted above, `Span` cannot be `const`. First-class'd structs are no different, so fields of type `ValueTuple`, `Range`, and as noted above, `Span` cannot be `const`.
Also `ref structs`, which makes slightly more sense. That's probably only because you'd be able to get a reference to a `ref struct` on the heap, something which shouldn't exist, by using reflection. Also `ref structs`, which makes slightly more sense. That's probably only because you'd be able to get a reference to a `ref struct` on the heap, something which shouldn't exist, by using reflection.
## Deceptive collection type names ## Deceptive collection type names
`IReadOnly{Collection,Dictionary,List,Set}` are for getting read-only views of the collections that implement them. They do not mean the collection is immutable (there are [separate classes](https://learn.microsoft.com/en-us/dotnet/api/system.collections.immutable?view=net-6.0) for that). The same goes for `ReadOnlySpan`. `IReadOnly{Collection,Dictionary,List,Set}` are for getting read-only views of the collections that implement them. They do not mean the collection is immutable (there are [separate classes](https://learn.microsoft.com/dotnet/api/system.collections.immutable?view=net-6.0) for that). The same goes for `ReadOnlySpan`.
> Kotlin got this right by calling its interfaces e.g. `List`/`MutableList` instead of `IReadOnlyList`/`IList`. (And it also fixed the inheritance hierarchy.) > Kotlin got this right by calling its interfaces e.g. `List`/`MutableList` instead of `IReadOnlyList`/`IList`. (And it also fixed the inheritance hierarchy.)
@ -117,12 +117,12 @@ public static ReadOnlySpan<TTo> UnsafeDowncast<TFrom, TTo>(ReadOnlySpan<TFrom> s
## MSBuild `Condition` placement ## MSBuild `Condition` placement
On (older versions of?) VS, `Condition` is ignored if placed on a property/item. On (older versions of?) VS, `Condition` is ignored if placed on a property/item.
It's also limited to a certain subset of expressions when placed on a `<PackageReference/>` (according to [docs](https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference-condition) circa .NET 8). It's also limited to a certain subset of expressions when placed on a `<PackageReference/>` (according to [docs](https://learn.microsoft.com/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference-condition) circa .NET 8).
Create a dedicated `<PropertyGroup/>`/`<ItemGroup/>`. Create a dedicated `<PropertyGroup/>`/`<ItemGroup/>`.
## MSBuild project evaluation (without build) ## MSBuild project evaluation (without build)
[`dotnet publish --getProperty`](https://learn.microsoft.com/en-us/visualstudio/msbuild/evaluate-items-and-properties#use-command-line-options-to-output-values) [`dotnet publish --getProperty`](https://learn.microsoft.com/visualstudio/msbuild/evaluate-items-and-properties#use-command-line-options-to-output-values)
Example: Example:
``` ```
@ -147,7 +147,7 @@ If a string literal contains a date, *even if it's being deserialised to a strin
## NuGet resources are all for old CLI ## NuGet resources are all for old CLI
[up-to-date docs on MSDN](https://learn.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli) [up-to-date docs on MSDN](https://learn.microsoft.com/nuget/consume-packages/install-use-packages-dotnet-cli)
`dotnet list $PWD/BizHawk.sln package --outdated` will list outdated `<PackageReference/>`s (betas are **ignored** without `--include-prerelease`—if there are only betas published, it sees no releases and prints "Not found"). There is no built-in command for updating them automatically. `dotnet list $PWD/BizHawk.sln package --outdated` will list outdated `<PackageReference/>`s (betas are **ignored** without `--include-prerelease`—if there are only betas published, it sees no releases and prints "Not found"). There is no built-in command for updating them automatically.
@ -168,7 +168,7 @@ See [dotnet/csharplang#53622](https://github.com/dotnet/csharplang/issues/53622)
## Preprocessor TFM constants and .NET Standard ## Preprocessor TFM constants and .NET Standard
The table [here](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation) is good for reference, but mind the note hidden at the bottom: The table [here](https://learn.microsoft.com/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation) is good for reference, but mind the note hidden at the bottom:
> The `NETSTANDARD<x>_<y>_OR_GREATER` symbols are only defined for .NET Standard targets, and not for targets that implement .NET Standard [...] > The `NETSTANDARD<x>_<y>_OR_GREATER` symbols are only defined for .NET Standard targets, and not for targets that implement .NET Standard [...]
That is, you must use `#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER)` and not just `#if !NETSTANDARD2_1_OR_GREATER`. That is, you must use `#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER)` and not just `#if !NETSTANDARD2_1_OR_GREATER`.
@ -185,11 +185,11 @@ It seems that `Guid`'s implementation *is* stable across instances, and even acr
## `System.Drawing.Color.*` rendered ## `System.Drawing.Color.*` rendered
[Docs for `Color`](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.color?view=netframework-4.8) don't include any pictures, so [here's a nice chart](https://user-images.githubusercontent.com/13409956/226146254-9a6fc384-c822-41e8-ae6a-3106f9e2986c.svg). [Docs for `Color`](https://learn.microsoft.com/dotnet/api/system.drawing.color?view=netframework-4.8) don't include any pictures, so [here's a nice chart](https://user-images.githubusercontent.com/13409956/226146254-9a6fc384-c822-41e8-ae6a-3106f9e2986c.svg).
## `System.Drawing.SystemIcons` rendered ## `System.Drawing.SystemIcons` rendered
[Docs for `SystemIcons`](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.systemicons?view=netframework-4.8) don't include any pictures, so here they are (Win10, Mono 6.12.x): [Docs for `SystemIcons`](https://learn.microsoft.com/dotnet/api/system.drawing.systemicons?view=netframework-4.8) don't include any pictures, so here they are (Win10, Mono 6.12.x):
![SystemIcons_Win10](https://user-images.githubusercontent.com/13409956/217321727-b3527c87-3ad9-44bb-8276-01afde65a939.png) ![SystemIcons_Win10](https://user-images.githubusercontent.com/13409956/217321727-b3527c87-3ad9-44bb-8276-01afde65a939.png)
![SystemIcons_Mono](https://user-images.githubusercontent.com/13409956/217311223-0d6acd76-203b-4694-9f45-4e4b8acc184b.png) ![SystemIcons_Mono](https://user-images.githubusercontent.com/13409956/217311223-0d6acd76-203b-4694-9f45-4e4b8acc184b.png)
@ -198,7 +198,7 @@ Notice also the default window icon (`Form.Icon`): on Windows, it's a distinct i
## `[ThreadStatic]` field initialisation ## `[ThreadStatic]` field initialisation
Per [docs](https://learn.microsoft.com/en-us/dotnet/api/system.threadstaticattribute?view=netstandard-2.0#remarks) ([simpler](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2019#rule-description)), static fields initialisation is moved to the static constructor in IL, which runs on at most 1 thread, so a `[ThreadStatic]` field will be `default` on all other threads if initialised in the usual way. Per [docs](https://learn.microsoft.com/dotnet/api/system.threadstaticattribute?view=netstandard-2.0#remarks) ([simpler](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2019#rule-description)), static fields initialisation is moved to the static constructor in IL, which runs on at most 1 thread, so a `[ThreadStatic]` field will be `default` on all other threads if initialised in the usual way.
Incorrect usage in BizHawk *should* be flagged with CA2019, but apparently it's not working in CI. Incorrect usage in BizHawk *should* be flagged with CA2019, but apparently it's not working in CI.
@ -210,7 +210,7 @@ If an object being the wrong type is *exceptional*—the method can't handle it
## Type constraints (`where` clauses) ## Type constraints (`where` clauses)
`class` in `where` clauses does not mean "not abstract", it means "reference type". Similarly, `struct` means "value type". There's a lot of complexity re: nullability, so [check the docs](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters) if you're writing a generic method. `class` in `where` clauses does not mean "not abstract", it means "reference type". Similarly, `struct` means "value type". There's a lot of complexity re: nullability, so [check the docs](https://learn.microsoft.com/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters) if you're writing a generic method.
TODO euler diagram TODO euler diagram