diff --git a/docs/core/compatibility/interop/8.0/jsfunctionbinding-constructor.md b/docs/core/compatibility/interop/8.0/jsfunctionbinding-constructor.md index 5399c5e6b291b..05953c8076a1a 100644 --- a/docs/core/compatibility/interop/8.0/jsfunctionbinding-constructor.md +++ b/docs/core/compatibility/interop/8.0/jsfunctionbinding-constructor.md @@ -9,11 +9,11 @@ The implicit public default constructor for `System.Runtime.InteropServices.Java ## Previous behavior -Previously, you could create empty instances of . +Previously, you could create empty instances of `System.Runtime.InteropServices.JavaScript.JSFunctionBinding`. ## New behavior -Starting in .NET 8, you can't instantiate a object. +Starting in .NET 8, you can't instantiate a `System.Runtime.InteropServices.JavaScript.JSFunctionBinding` object. ## Version introduced diff --git a/docs/core/extensions/httpclient-http3.md b/docs/core/extensions/httpclient-http3.md index bf21ff7e784df..a84d9b6dc05ec 100644 --- a/docs/core/extensions/httpclient-http3.md +++ b/docs/core/extensions/httpclient-http3.md @@ -17,7 +17,6 @@ HTTP/3 and QUIC both have several benefits compared to HTTP/1.1 and HTTP/2: - Supports transitioning between networks. This feature is useful for mobile devices where it's common to switch between WIFI and cellular networks as a mobile device changes location. Currently, HTTP/1.1 and HTTP/2 connections fail with an error when switching networks. An app or web browser must retry any failed HTTP requests. HTTP/3 allows the app or web browser to seamlessly continue when a network changes. and Kestrel don't support network transitions in .NET 7. It may be available in a future release. > [!IMPORTANT] -> > Apps configured to take advantage of HTTP/3 should be designed to also support HTTP/1.1 and HTTP/2. If issues are identified in HTTP/3, it's recommend disabling HTTP/3 until the issues are resolved in a future release of .NET. ## HttpClient settings @@ -29,7 +28,7 @@ The HTTP version can be configured by setting `HttpRequestMessage.Version` to 3. ## Platform dependencies -HTTP/3 uses QUIC as its transport protocol. The .NET implementation of HTTP/3 uses [MsQuic](https://github.com/microsoft/msquic) to provide QUIC functionality. As a result, .NET support of HTTP/3 depends on MsQuic platform requirements, which are documented in [QUIC Platform dependencies](../../fundamentals/networking/quic/quic-overview.md#platform-dependencies). If the platform that HttpClient is running on doesn't have all the requirements for HTTP/3, then it's disabled. +HTTP/3 uses QUIC as its transport protocol. The .NET implementation of HTTP/3 uses [MsQuic](https://github.com/microsoft/msquic) to provide QUIC functionality. As a result, .NET support of HTTP/3 depends on MsQuic platform requirements. For more information on how to install **MsQuic**, see [QUIC Platform dependencies](../../fundamentals/networking/quic/quic-overview.md#platform-dependencies). If the platform that HttpClient is running on doesn't have all the requirements for HTTP/3, then it's disabled. ## Using HttpClient @@ -54,11 +53,11 @@ Alternatively, you can call logger) : BackgroundService { private const string ClassName = nameof(ScopedBackgroundService); @@ -19,7 +19,7 @@ private async Task DoWorkAsync(CancellationToken stoppingToken) logger.LogInformation( "{Name} is working.", ClassName); - using (IServiceScope scope = serviceProvider.CreateScope()) + using (IServiceScope scope = serviceScopeFactory.CreateScope()) { IScopedProcessingService scopedProcessingService = scope.ServiceProvider.GetRequiredService(); diff --git a/docs/core/install/how-to-detect-installed-versions.md b/docs/core/install/how-to-detect-installed-versions.md index af76229d1c5cf..e8617db257148 100644 --- a/docs/core/install/how-to-detect-installed-versions.md +++ b/docs/core/install/how-to-detect-installed-versions.md @@ -95,20 +95,20 @@ Microsoft.WindowsDesktop.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.Win ::: zone pivot="os-linux" ```bash -Microsoft.AspNetCore.All 2.1.7 [/home/user/dotnet/shared/Microsoft.AspNetCore.All] -Microsoft.AspNetCore.All 2.1.13 [/home/user/dotnet/shared/Microsoft.AspNetCore.All] -Microsoft.AspNetCore.App 2.1.7 [/home/user/dotnet/shared/Microsoft.AspNetCore.App] -Microsoft.AspNetCore.App 2.1.13 [/home/user/dotnet/shared/Microsoft.AspNetCore.App] -Microsoft.AspNetCore.App 3.1.0 [/home/user/dotnet/shared/Microsoft.AspNetCore.App] -Microsoft.AspNetCore.App 5.0.0 [/home/user/dotnet/shared/Microsoft.AspNetCore.App] -Microsoft.AspNetCore.App 6.0.0 [/home/user/dotnet/shared/Microsoft.AspNetCore.App] -Microsoft.NETCore.App 2.1.7 [/home/user/dotnet/shared/Microsoft.NETCore.App] -Microsoft.NETCore.App 2.1.13 [/home/user/dotnet/shared/Microsoft.NETCore.App] -Microsoft.NETCore.App 3.1.0 [/home/user/dotnet/shared/Microsoft.NETCore.App] -Microsoft.NETCore.App 5.0.0 [/home/user/dotnet/shared/Microsoft.NETCore.App] -Microsoft.NETCore.App 6.0.0 [/home/user/dotnet/shared/Microsoft.NETCore.App] -Microsoft.NETCore.App 7.0.0 [/home/user/dotnet/shared/Microsoft.NETCore.App] -Microsoft.NETCore.App 8.0.0 [/home/user/dotnet/shared/Microsoft.NETCore.App] +Microsoft.AspNetCore.All 2.1.7 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.All] +Microsoft.AspNetCore.All 2.1.13 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.All] +Microsoft.AspNetCore.App 2.1.7 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.AspNetCore.App 2.1.13 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.AspNetCore.App 3.1.0 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.AspNetCore.App 5.0.0 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.AspNetCore.App 6.0.0 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.NETCore.App 2.1.7 [/usr/lib/dotnet/shared/Microsoft.NETCore.App] +Microsoft.NETCore.App 2.1.13 [/usr/lib/dotnet/shared/Microsoft.NETCore.App] +Microsoft.NETCore.App 3.1.0 [/usr/lib/dotnet/shared/Microsoft.NETCore.App] +Microsoft.NETCore.App 5.0.0 [/usr/lib/dotnet/shared/Microsoft.NETCore.App] +Microsoft.NETCore.App 6.0.0 [/usr/lib/dotnet/shared/Microsoft.NETCore.App] +Microsoft.NETCore.App 7.0.0 [/usr/lib/dotnet/shared/Microsoft.NETCore.App] +Microsoft.NETCore.App 8.0.0 [/usr/lib/dotnet/shared/Microsoft.NETCore.App] ``` ::: zone-end @@ -156,13 +156,19 @@ _C:\\program files\\dotnet\\shared\\{runtime-type}\\{version}\\_ ::: zone pivot="os-linux" - **dotnet executable**\ -_/home/user/share/dotnet/dotnet_ +_/home/user/.dotnet/dotnet_\ +_/usr/lib/dotnet/dotnet_\ +_/usr/share/dotnet/dotnet_\ - **.NET SDK**\ -_/home/user/share/dotnet/sdk/{version}/_ +_/home/user/.dotnet/sdk/{version}/_\ +_/usr/lib/dotnet/sdk/{version}/_\ +_/usr/share/dotnet/sdk/{version}/_\ - **.NET Runtime**\ -_/home/user/share/dotnet/shared/{runtime-type}/{version}/_ +_/home/user/.dotnet/shared/{runtime-type}/{version}/_\ +_/usr/lib/dotnet/shared/{runtime-type}/{version}/_\ +_/usr/share/dotnet/shared/{runtime-type}/{version}/_\ ::: zone-end diff --git a/docs/core/install/includes/linux-install-package-manager-x64-vs-arm-ubuntu.md b/docs/core/install/includes/linux-install-package-manager-x64-vs-arm-ubuntu.md new file mode 100644 index 0000000000000..4249ebf3f1c94 --- /dev/null +++ b/docs/core/install/includes/linux-install-package-manager-x64-vs-arm-ubuntu.md @@ -0,0 +1,14 @@ +--- +author: adegeo +ms.author: adegeo +ms.date: 12/29/2023 +ms.topic: include +--- + +> [!IMPORTANT] +> Using a package manager to install .NET from the **Microsoft pacakge feed** only supports the **x64** architecture. Other architectures, such as **Arm**, aren't supported by the **Microsoft package feed**. Use the Ubuntu feed or manually install .NET. Be cautious of package mix up problems. For more information, see [.NET package mix ups on Linux](../linux-package-mixup.md?pivots=os-linux-ubuntu#whats-going-on). + +For more information on installing .NET **without a package manager**, see one of the following articles: + +- [Use the `install-dotnet` script to install .NET.](../linux-scripted-manual.md#scripted-install) +- [Manually install .NET.](../linux-scripted-manual.md#manual-install) diff --git a/docs/core/install/includes/linux-install-package-manager-x64-vs-arm.md b/docs/core/install/includes/linux-install-package-manager-x64-vs-arm.md index c2ab91ee69e2f..01c85dbb05a71 100644 --- a/docs/core/install/includes/linux-install-package-manager-x64-vs-arm.md +++ b/docs/core/install/includes/linux-install-package-manager-x64-vs-arm.md @@ -1,14 +1,14 @@ --- author: adegeo ms.author: adegeo -ms.date: 11/14/2023 +ms.date: 12/29/2023 ms.topic: include --- > [!IMPORTANT] -> Package manager installs are only supported on the **x64** architecture. Other architectures, such as **Arm**, must install .NET by some other means such as with Snap, an installer script, or through a manual binary installation. +> Using a package manager to install .NET from the **Microsoft pacakge feed** only supports the **x64** architecture. Other architectures, such as **Arm**, aren't supported by the **Microsoft package feed**. For more information on installing .NET **without a package manager**, see one of the following articles: -- [Alternatively install .NET with `install-dotnet` script.](../linux-scripted-manual.md#scripted-install) -- [Manually install .NET](../linux-scripted-manual.md#manual-install) +- [Use the `install-dotnet` script to install .NET.](../linux-scripted-manual.md#scripted-install) +- [Manually install .NET.](../linux-scripted-manual.md#manual-install) diff --git a/docs/core/install/linux-package-mixup.md b/docs/core/install/linux-package-mixup.md index 534ec59ffcb41..f1aa06116e3e4 100644 --- a/docs/core/install/linux-package-mixup.md +++ b/docs/core/install/linux-package-mixup.md @@ -2,6 +2,7 @@ title: Troubleshoot .NET package mix ups on Linux description: Learn about how to troubleshoot strange .NET package errors on Linux. These errors may occur when you run the dotnet command. author: omajid +ms.author: adegeo ms.date: 03/01/2023 no-loc: ['usr','lib64','share','dotnet','libhostfxr.so', 'fxr', 'FrameworkList.xml', 'System.IO.FileNotFoundException'] zone_pivot_groups: operating-systems-set-two @@ -202,7 +203,7 @@ Configure your package manager to ignore the .NET packages from the distribution > Use the `apt-cache policy` command to find the source: > > ```bash - > apt-cache policy '~ndotnet.*' | grep -v microsoft | grep '/ubuntu' | cut -d"/" -f3 | sort -u + > apt-cache policy '~ndotnet.*' | grep -v microsoft | grep '/ubuntu' | grep updates | cut -d"/" -f3 | sort -u > ``` 01. Reinstall .NET from the Microsoft package feed. For more information, see [Install .NET on Linux](linux.md). If using Ubuntu, see [My Ubuntu distribution doesn't include the .NET version I want, or I need an out-of-support .NET version](linux-ubuntu.md#my-ubuntu-distribution-doesnt-include-the-net-version-i-want-or-i-need-an-out-of-support-net-version). diff --git a/docs/core/install/linux-scripted-manual.md b/docs/core/install/linux-scripted-manual.md index 813b114a55b93..26b21a7f2c6ef 100644 --- a/docs/core/install/linux-scripted-manual.md +++ b/docs/core/install/linux-scripted-manual.md @@ -131,7 +131,9 @@ Different versions of .NET can be extracted to the same folder, which coexist si ### Example -The following commands set the environment variable `DOTNET_ROOT` to the current working directory followed by `.dotnet`. They then create the directory if it doesn't exist and extract the contents of the file specified by the `DOTNET_FILE` environment variable to the `.dotnet` directory. Both the `.dotnet` directory and its `tools` subdirectory are added to the `PATH` environment variable. + + +The following commands use Bash to set the environment variable `DOTNET_ROOT` to the current working directory followed by `.dotnet`. That directory is created if it doesn't exist. The `DOTNET_FILE` environment variable is the filename of the .NET binary release you want to install. This file is extracted to the `DOTNET_ROOT` directory. Both the `DOTNET_ROOT` directory and its `tools` subdirectory are added to the `PATH` environment variable. > [!IMPORTANT] > If you run these commands, remember to change the `DOTNET_FILE` value to the name of the .NET binary you downloaded. @@ -145,7 +147,13 @@ mkdir -p "$DOTNET_ROOT" && tar zxf "$DOTNET_FILE" -C "$DOTNET_ROOT" export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools ``` -The preceding install script approach allows installing different versions into separate locations so you can choose explicitly which one to use by which app. However, you can still install multiple versions of .NET to the same folder. +You can install more than one version of .NET in the same folder. + +You can also install .NET to the home directory identified by the `HOME` variable or `~` path: + +```bash +export DOTNET_ROOT=$HOME/.dotnet +``` ## Verify downloaded binaries @@ -157,7 +165,7 @@ The preceding install script approach allows installing different versions into If you used the previous install script, the variables set only apply to your current terminal session. Add them to your shell profile. There are many different shells available for Linux and each has a different profile. For example: -- **Bash Shell**: *~/.bash_profile*, *~/.bashrc* +- **Bash Shell**: *~/.bash_profile* or *~/.bashrc* - **Korn Shell**: *~/.kshrc* or *.profile* - **Z Shell**: *~/.zshrc* or *.zprofile* @@ -173,7 +181,7 @@ Set the following two environment variables in your shell profile: - `PATH` - This variable should include both the `DOTNET_ROOT` folder and the user's _.dotnet/tools_ folder: + This variable should include both the `DOTNET_ROOT` folder and the `DOTNET_ROOT/tools` folder: ```bash export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools diff --git a/docs/core/install/linux-ubuntu-2304.md b/docs/core/install/linux-ubuntu-2304.md index 81beee82c174f..3f669dffaf79b 100644 --- a/docs/core/install/linux-ubuntu-2304.md +++ b/docs/core/install/linux-ubuntu-2304.md @@ -12,7 +12,7 @@ This article discusses how to install .NET on Ubuntu 23.04; .NET 8, .NET 7, and [!INCLUDE [linux-intro-sdk-vs-runtime](includes/linux-intro-sdk-vs-runtime.md)] -[!INCLUDE [linux-install-package-manager-x64-vs-arm](includes/linux-install-package-manager-x64-vs-arm.md)] +[!INCLUDE [linux-install-package-manager-x64-vs-arm-ubuntu](includes/linux-install-package-manager-x64-vs-arm-ubuntu.md)] .NET is available in the Ubuntu package manager feeds, as well as the Microsoft package repository. However, you should only use one or the other to install .NET. If you want to use the Microsoft package repository, see [How to register the Microsoft package repository](linux-ubuntu.md#register-the-microsoft-package-repository). diff --git a/docs/core/install/linux-ubuntu-2310.md b/docs/core/install/linux-ubuntu-2310.md index 075daae902451..55aaf61b127ca 100644 --- a/docs/core/install/linux-ubuntu-2310.md +++ b/docs/core/install/linux-ubuntu-2310.md @@ -12,7 +12,7 @@ This article discusses how to install .NET on Ubuntu 23.10; .NET 8, .NET 7, and [!INCLUDE [linux-intro-sdk-vs-runtime](includes/linux-intro-sdk-vs-runtime.md)] -[!INCLUDE [linux-install-package-manager-x64-vs-arm](includes/linux-install-package-manager-x64-vs-arm.md)] +[!INCLUDE [linux-install-package-manager-x64-vs-arm-ubuntu](includes/linux-install-package-manager-x64-vs-arm-ubuntu.md)] .NET is available in the Ubuntu package manager feeds, as well as the Microsoft package repository. However, you should only use one or the other to install .NET. If you want to use the Microsoft package repository, see [How to register the Microsoft package repository](linux-ubuntu.md#register-the-microsoft-package-repository). diff --git a/docs/core/install/macos-notarization-issues.md b/docs/core/install/macos-notarization-issues.md index cd77efed3ed04..dec21fe22328a 100644 --- a/docs/core/install/macos-notarization-issues.md +++ b/docs/core/install/macos-notarization-issues.md @@ -12,7 +12,7 @@ Beginning with macOS Catalina (version 10.15), all software built after June 1, ## Installing .NET -The installers for .NET (both runtime and SDK) have been notarized since February 18, 2020. Prior released versions aren't notarized. You can manually install a non-notarized version of .NET by first downloading the installer, and then using the `sudo installer` command. For more information, see [Download and manually install for macOS](./macos.md#download-and-manually-install). +The installers for .NET (both runtime and SDK) have been notarized since February 18, 2020. Prior released versions aren't notarized. You can manually install a non-notarized version of .NET by first downloading the installer, and then using the `sudo installer` command. For more information, see [Download and manually install for macOS](./macos.md#manual-install). ## Native appHost diff --git a/docs/core/install/macos.md b/docs/core/install/macos.md index 95a01203310dc..da7b65f1d8ac5 100644 --- a/docs/core/install/macos.md +++ b/docs/core/install/macos.md @@ -81,7 +81,7 @@ brew update brew install mono-libgdiplus ``` -## Install with an installer +## Automated install macOS has standalone installers that can be used to install .NET: @@ -89,46 +89,46 @@ macOS has standalone installers that can be used to install .NET: - ✔️ [.NET 7 downloads](https://dotnet.microsoft.com/download/dotnet/7.0) - ✔️ [.NET 6 downloads](https://dotnet.microsoft.com/download/dotnet/6.0) -## Download and manually install +## Manual install As an alternative to the macOS installers for .NET, you can download and manually install the SDK and runtime. Manual installation is usually performed as part of continuous integration testing. For a developer or user, it's generally better to use an [installer](https://dotnet.microsoft.com/download/dotnet). -First, download a **binary** release for either the SDK or the runtime from one of the following sites. If you install the .NET SDK, you won't need to install the corresponding runtime: +Download a **binary** release for either the SDK or the runtime from one of the following sites. The .NET SDK includes the corresponding runtime: - ✔️ [.NET 8 downloads](https://dotnet.microsoft.com/download/dotnet/8.0) - ✔️ [.NET 7 downloads](https://dotnet.microsoft.com/download/dotnet/7.0) - ✔️ [.NET 6 downloads](https://dotnet.microsoft.com/download/dotnet/6.0) - [All .NET downloads](https://dotnet.microsoft.com/download/dotnet) -Next, extract the downloaded file and use the `export` command to set `DOTNET_ROOT` to the extracted folder's location and then ensure .NET is in PATH. This should make the .NET CLI commands available at the terminal. For more information about .NET environment variables, see [.NET SDK and CLI environment variables](../tools/dotnet-environment-variables.md#net-sdk-and-cli-environment-variables). +Extract the downloaded file and use the `export` command to set `DOTNET_ROOT` to the extracted folder's location and then ensure .NET is in PATH. Exporting `DOTNET_ROOT` makes the .NET CLI commands available in the terminal. For more information about .NET environment variables, see [.NET SDK and CLI environment variables](../tools/dotnet-environment-variables.md#net-sdk-and-cli-environment-variables). -Alternatively, after downloading the .NET binary, the following commands can be run from the directory where the file is saved to extract the runtime. These commands also make the .NET CLI commands available at the terminal and set the required environment variables. **Remember to change the `DOTNET_FILE` value to the name of the downloaded binary**: +Different versions of .NET can be extracted to the same folder, which coexist side-by-side. + +### Example + +The following commands use Bash to set the environment variable `DOTNET_ROOT` to the current working directory followed by `.dotnet`. That directory is created if it doesn't exist. The `DOTNET_FILE` environment variable is the filename of the .NET binary release you want to install. This file is extracted to the `DOTNET_ROOT` directory. Both the `DOTNET_ROOT` directory and its `tools` subdirectory are added to the `PATH` environment variable. + +> [!IMPORTANT] +> If you run these commands, remember to change the `DOTNET_FILE` value to the name of the .NET binary you downloaded. ```bash DOTNET_FILE=dotnet-sdk-8.0.100-osx-x64.tar.gz -export DOTNET_ROOT=$(pwd)/dotnet +export DOTNET_ROOT=$(pwd)/.dotnet mkdir -p "$DOTNET_ROOT" && tar zxf "$DOTNET_FILE" -C "$DOTNET_ROOT" export PATH=$PATH:$DOTNET_ROOT ``` -> [!TIP] -> The preceding `export` commands only make the .NET CLI commands available for the terminal session in which it was run. -> -> You can edit your shell profile to permanently add the commands. There are a number of different shells available for Linux and each has a different profile. For example: -> -> - **Bash Shell**: *~/.bash_profile*, *~/.bashrc* -> - **Korn Shell**: *~/.kshrc* or *.profile* -> - **Z Shell**: *~/.zshrc* or *.zprofile* -> -> Edit the appropriate source file for your shell and add `:$HOME/dotnet` to the end of the existing `PATH` statement. If no `PATH` statement is included, add a new line with `export PATH=$PATH:$HOME/dotnet`. -> -> Also, add `export DOTNET_ROOT=$HOME/dotnet` to the end of the file. +You can install more than one version of .NET in the same folder. + +You can also install .NET to the home directory identified by the `HOME` variable or `~` path: -This approach lets you install different versions into separate locations and choose explicitly which one to use by which application. +```bash +export DOTNET_ROOT=$HOME/.dotnet +``` ## Verify downloaded binaries @@ -136,6 +136,32 @@ This approach lets you install different versions into separate locations and ch [!INCLUDE [verify-download-macos-linux](includes/verify-download-macos-linux.md)] +## Set environment variables system-wide + +If you used the instructions in the [Manual install example](#example) section, the variables set only apply to your current terminal session. Add them to your shell profile. There are many different shells available for macOS and each has a different profile. For example: + +- **Bash Shell**: *~/.profile*, */etc/profile* +- **Korn Shell**: *~/.kshrc* or *.profile* +- **Z Shell**: *~/.zshrc* or *.zprofile* + +Set the following two environment variables in your shell profile: + +- `DOTNET_ROOT` + + This variable is set to the folder .NET was installed to, such as `$HOME/.dotnet`: + + ```bash + export DOTNET_ROOT=$HOME/.dotnet + ``` + +- `PATH` + + This variable should include both the `DOTNET_ROOT` folder and the `DOTNET_ROOT/tools` folder: + + ```bash + export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools + ``` + ## Arm-based Macs The following sections describe things you should consider when installing .NET on an Arm-based Mac. diff --git a/docs/core/runtime-discovery/troubleshoot-app-launch.md b/docs/core/runtime-discovery/troubleshoot-app-launch.md index b0664f0e8ded2..0cb388d4cc9bd 100644 --- a/docs/core/runtime-discovery/troubleshoot-app-launch.md +++ b/docs/core/runtime-discovery/troubleshoot-app-launch.md @@ -240,15 +240,15 @@ For more information on installation using the script, see [Install with bash au You can download a binary archive of .NET from the [download page](https://dotnet.microsoft.com/download/dotnet). From the **Binaries** column of the runtime download, download the binary release matching the required architecture. Extract the downloaded archive to the ".NET location" specified in the error message. ::: zone pivot="os-windows" -For more details on manual installation, see [Install .NET on Windows](../install/windows.md#install-with-powershell-automation) +For more information about manual installation, see [Install .NET on Windows](../install/windows.md#install-with-powershell-automation) ::: zone-end ::: zone pivot="os-linux" -For more details on manual installation, see [Install .NET on Linux](../install/linux.md#manual-installation) +For more information about manual installation, see [Install .NET on Linux](../install/linux.md#manual-installation) ::: zone-end ::: zone pivot="os-macos" -For more details on manual installation, see [Install .NET on macOS](../install/macos.md#download-and-manually-install) +For more information about manual installation, see [Install .NET on macOS](../install/macos.md#manual-install) ::: zone-end ### Configure roll-forward behavior diff --git a/docs/core/testing/unit-testing-mstest-runner-vs-vstest.md b/docs/core/testing/unit-testing-mstest-runner-vs-vstest.md index f792695c2ddb6..574564d0b1ce1 100644 --- a/docs/core/testing/unit-testing-mstest-runner-vs-vstest.md +++ b/docs/core/testing/unit-testing-mstest-runner-vs-vstest.md @@ -16,11 +16,11 @@ Tests are executed in different ways depending on the runner. ### Execute VSTest tests -VSTest ships with Visual Studio, .NET SDK and also as a standalone tool in the [Microsoft.TestingPlatform](https://www.nuget.org/packages/Microsoft.TestingPlatform) NuGet package. VSTest uses a runner executable to run tests, this runner is called `vstest.console.exe`, and can be used directly or through `dotnet test`. +VSTest ships with Visual Studio, the .NET SDK, and as a standalone tool in the [Microsoft.Testing.Platform](https://www.nuget.org/packages/Microsoft.Testing.Platform) NuGet package. VSTest uses a runner executable to run tests, called `vstest.console.exe`, which can be used directly or through `dotnet test`. ### Execute MSTest runner tests -MSTest is embedded directly into your test project, and doesn't ship any extra executables. Running your project executable directly runs yours tests. For more information on running MSTest tests, see [MSTest runner overview: Run and debug tests](unit-testing-mstest-runner-intro.md#run-and-debug-tests). +MSTest is embedded directly into your test project and doesn't ship any extra executables. When you run your project executable, your tests run. For more information on running MSTest tests, see [MSTest runner overview: Run and debug tests](unit-testing-mstest-runner-intro.md#run-and-debug-tests). ## Namespaces and NuGet packages @@ -38,4 +38,4 @@ The MSTest runner is based on [Microsoft.Testing.Platform](https://www.nuget.org ## Executables -VSTest ships multiple executables, the most known are `vstest.console.exe`, `testhost.exe`, and `datacollector.exe`. Whereas MSTest is embedded directly into your test project, and doesn't ship any other executables. The executable your test project compiles to, is used to host all the testing tools, and carry out all the tasks needed to run tests. +VSTest ships multiple executables, notably `vstest.console.exe`, `testhost.exe`, and `datacollector.exe`. However, MSTest is embedded directly into your test project and doesn't ship any other executables. The executable your test project compiles to is used to host all the testing tools and carry out all the tasks needed to run tests. diff --git a/docs/csharp/language-reference/compiler-options/language.md b/docs/csharp/language-reference/compiler-options/language.md index b9a3d76406a62..29b15da1890b2 100644 --- a/docs/csharp/language-reference/compiler-options/language.md +++ b/docs/csharp/language-reference/compiler-options/language.md @@ -107,7 +107,7 @@ For information about how to set this compiler option programmatically, see [!NOTE] +> .NET 7+ is only compatible with 2.2+ versions of libmsquic. -- OpenSSL 3+ or 1.1 - depends on the default OpenSSL version for the distribution version, for example, OpenSSL 3 for [Ubuntu 22](https://packages.ubuntu.com/jammy/openssl) and OpenSSL 1.1 for [Ubuntu 20](https://packages.ubuntu.com/focal/utils/openssl). +The `libmsquic` package is required on Linux. This package is published in Microsoft's official Linux package repository, . You must add this repository to your package manager before installing the package. For more information, see [Linux Software Repository for Microsoft Products](/linux/packages). -- libnuma 1 +> [!CAUTION] +> Adding the Microsoft pacakge repository may conflict with your distribution's repository when your distribution's repository provides .NET and other Microsoft packages. To avoid or troubleshoot package mixups, review [Troubleshoot .NET errors related to missing files on Linux](../../../core/install/linux-package-mixup.md#whats-going-on). -On Linux, libmsquic is published via Microsoft's official Linux package repository, . To consume libmsquic, you must add it manually. For more information, see [Linux Software Repository for Microsoft Products](/windows-server/administration/linux-package-repository-for-microsoft-software). After configuring the package feed, it's installed via the package manager of your distro, for example, for Ubuntu: +##### Examples -```bash -sudo apt install libmsquic -``` +Here are some examples of using a package manager to install `libmsquic`: -> [!NOTE] -> .NET 7 is only compatible with 2.2+ versions of libmsquic. +- **APT** + + ```bash + sudo apt-get libmsquic + ``` + +- **APK** + + ```bash + sudo apk add libmsquic + ``` + +- **DNF** + + ```bash + sudo dnf install libmsquic + ``` + +- **zypper** + + ```bash + sudo zypper install libmsquic + ``` + +- **YUM** + + ```bash + sudo yum install libmsquic + ``` + +##### Dependencies of libmsquic + +All the following dependencies are stated in the `libmsquic` package manifest and are automatically installed by the package manager: + +- OpenSSL 3+ or 1.1 - depends on the default OpenSSL version for the distribution version, for example, OpenSSL 3 for [Ubuntu 22](https://packages.ubuntu.com/jammy/openssl) and OpenSSL 1.1 for [Ubuntu 20](https://packages.ubuntu.com/focal/utils/openssl). + +- libnuma 1 ### macOS diff --git a/docs/fundamentals/runtime-libraries/includes/c-and-posix-cultures.md b/docs/fundamentals/runtime-libraries/includes/c-and-posix-cultures.md new file mode 100644 index 0000000000000..1f96cbf12117c --- /dev/null +++ b/docs/fundamentals/runtime-libraries/includes/c-and-posix-cultures.md @@ -0,0 +1,2 @@ +> [!NOTE] +> **.NET Core running on Linux and macOS systems only:** The collation behavior for the C and Posix cultures is always case-sensitive because these cultures do not use the expected Unicode collation order. We recommend that you use a culture other than C or Posix for performing culture-sensitive, case-insensitive sorting operations. diff --git a/docs/fundamentals/runtime-libraries/includes/context.md b/docs/fundamentals/runtime-libraries/includes/context.md new file mode 100644 index 0000000000000..89814007b303e --- /dev/null +++ b/docs/fundamentals/runtime-libraries/includes/context.md @@ -0,0 +1 @@ +This article provides supplementary remarks to the reference documentation for this API. diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/appdomainex1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/appdomainex1.cs new file mode 100644 index 0000000000000..eac16aea7ba8c --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/appdomainex1.cs @@ -0,0 +1,77 @@ +// +using System; +using System.Globalization; + +public class Example +{ + public static void Main() + { + // Set the default culture and display the current date in the current application domain. + Info info1 = new Info(); + SetAppDomainCultures("fr-FR"); + + // Create a second application domain. + AppDomainSetup setup = new AppDomainSetup(); + setup.AppDomainInitializer = SetAppDomainCultures; + setup.AppDomainInitializerArguments = new string[] { "ru-RU" }; + AppDomain domain = AppDomain.CreateDomain("Domain2", null, setup); + // Create an Info object in the new application domain. + Info info2 = (Info)domain.CreateInstanceAndUnwrap(typeof(Example).Assembly.FullName, + "Info"); + + // Execute methods in the two application domains. + info2.DisplayDate(); + info2.DisplayCultures(); + + info1.DisplayDate(); + info1.DisplayCultures(); + } + + public static void SetAppDomainCultures(string[] names) + { + SetAppDomainCultures(names[0]); + } + + public static void SetAppDomainCultures(string name) + { + try + { + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture(name); + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture(name); + } + // If an exception occurs, we'll just fall back to the system default. + catch (CultureNotFoundException) + { + return; + } + catch (ArgumentException) + { + return; + } + } +} + +public class Info : MarshalByRefObject +{ + public void DisplayDate() + { + Console.WriteLine("Today is {0:D}", DateTime.Now); + } + + public void DisplayCultures() + { + Console.WriteLine("Application domain is {0}", AppDomain.CurrentDomain.Id); + Console.WriteLine("Default Culture: {0}", CultureInfo.DefaultThreadCurrentCulture); + Console.WriteLine("Default UI Culture: {0}", CultureInfo.DefaultThreadCurrentUICulture); + } +} +// The example displays the following output: +// Today is 14 октября 2011 г. +// Application domain is 2 +// Default Culture: ru-RU +// Default UI Culture: ru-RU +// Today is vendredi 14 octobre 2011 +// Application domain is 1 +// Default Culture: fr-FR +// Default UI Culture: fr-FR +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/asyncculture1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/asyncculture1.cs new file mode 100644 index 0000000000000..bda34aac05faa --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/asyncculture1.cs @@ -0,0 +1,66 @@ +// +using System; +using System.Globalization; +using System.Threading; +using System.Threading.Tasks; + +public class AsyncCultureEx1 +{ + public static void Main() + { + decimal[] values = { 163025412.32m, 18905365.59m }; + string formatString = "C2"; + + string FormatDelegate() + { + string output = $"Formatting using the {CultureInfo.CurrentCulture.Name} " + + "culture on thread {Thread.CurrentThread.ManagedThreadId}.\n"; + foreach (decimal value in values) + output += $"{value.ToString(formatString)} "; + + output += Environment.NewLine; + return output; + } + + Console.WriteLine($"The example is running on thread {Thread.CurrentThread.ManagedThreadId}"); + // Make the current culture different from the system culture. + Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}"); + if (CultureInfo.CurrentCulture.Name == "fr-FR") + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); + else + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR"); + + Console.WriteLine($"Changed the current culture to {CultureInfo.CurrentCulture.Name}.\n"); + + // Execute the delegate synchronously. + Console.WriteLine("Executing the delegate synchronously:"); + Console.WriteLine(FormatDelegate()); + + // Call an async delegate to format the values using one format string. + Console.WriteLine("Executing a task asynchronously:"); + var t1 = Task.Run(FormatDelegate); + Console.WriteLine(t1.Result); + + Console.WriteLine("Executing a task synchronously:"); + var t2 = new Task(FormatDelegate); + t2.RunSynchronously(); + Console.WriteLine(t2.Result); + } +} +// The example displays the following output: +// The example is running on thread 1 +// The current culture is en-US +// Changed the current culture to fr-FR. +// +// Executing the delegate synchronously: +// Formatting using the fr-FR culture on thread 1. +// 163 025 412,32 € 18 905 365,59 € +// +// Executing a task asynchronously: +// Formatting using the fr-FR culture on thread 3. +// 163 025 412,32 € 18 905 365,59 € +// +// Executing a task synchronously: +// Formatting using the fr-FR culture on thread 1. +// 163 025 412,32 € 18 905 365,59 € +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/asyncculture3.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/asyncculture3.cs new file mode 100644 index 0000000000000..743c06454f6c0 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/asyncculture3.cs @@ -0,0 +1,70 @@ +// +using System; +using System.Globalization; +using System.Threading; +using System.Threading.Tasks; + +public class AsyncCultureEx3 +{ + public static void Main() + { + decimal[] values = { 163025412.32m, 18905365.59m }; + string formatString = "C2"; + Func formatDelegate = () => + { + string output = String.Format("Formatting using the {0} culture on thread {1}.\n", + CultureInfo.CurrentCulture.Name, + Thread.CurrentThread.ManagedThreadId); + foreach (var value in values) + output += String.Format("{0} ", value.ToString(formatString)); + + output += Environment.NewLine; + return output; + }; + + Console.WriteLine("The example is running on thread {0}", + Thread.CurrentThread.ManagedThreadId); + // Make the current culture different from the system culture. + Console.WriteLine("The current culture is {0}", + CultureInfo.CurrentCulture.Name); + if (CultureInfo.CurrentCulture.Name == "fr-FR") + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); + else + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR"); + + Console.WriteLine("Changed the current culture to {0}.\n", + CultureInfo.CurrentCulture.Name); + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture; + + // Execute the delegate synchronously. + Console.WriteLine("Executing the delegate synchronously:"); + Console.WriteLine(formatDelegate()); + + // Call an async delegate to format the values using one format string. + Console.WriteLine("Executing a task asynchronously:"); + var t1 = Task.Run(formatDelegate); + Console.WriteLine(t1.Result); + + Console.WriteLine("Executing a task synchronously:"); + var t2 = new Task(formatDelegate); + t2.RunSynchronously(); + Console.WriteLine(t2.Result); + } +} +// The example displays the following output: +// The example is running on thread 1 +// The current culture is en-US +// Changed the current culture to fr-FR. +// +// Executing the delegate synchronously: +// Formatting using the fr-FR culture on thread 1. +// 163 025 412,32 € 18 905 365,59 € +// +// Executing a task asynchronously: +// Formatting using the fr-FR culture on thread 3. +// 163 025 412,32 € 18 905 365,59 € +// +// Executing a task synchronously: +// Formatting using the fr-FR culture on thread 1. +// 163 025 412,32 € 18 905 365,59 € +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/change1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/change1.cs new file mode 100644 index 0000000000000..f079c787e387d --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/change1.cs @@ -0,0 +1,25 @@ +// +using System; +using System.Globalization; + +public class ChangeEx1 +{ + public static void Main() + { + CultureInfo current = CultureInfo.CurrentCulture; + Console.WriteLine("The current culture is {0}", current.Name); + CultureInfo newCulture; + if (current.Name.Equals("fr-FR")) + newCulture = new CultureInfo("fr-LU"); + else + newCulture = new CultureInfo("fr-FR"); + + CultureInfo.CurrentCulture = newCulture; + Console.WriteLine("The current culture is now {0}", + CultureInfo.CurrentCulture.Name); + } +} +// The example displays output like the following: +// The current culture is en-US +// The current culture is now fr-FR +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/changeui1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/changeui1.cs new file mode 100644 index 0000000000000..6db5a3d52494d --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/changeui1.cs @@ -0,0 +1,25 @@ +// +using System; +using System.Globalization; + +public class ChangeUICultureEx +{ + public static void Main() + { + CultureInfo current = CultureInfo.CurrentUICulture; + Console.WriteLine("The current UI culture is {0}", current.Name); + CultureInfo newUICulture; + if (current.Name.Equals("sl-SI")) + newUICulture = new CultureInfo("hr-HR"); + else + newUICulture = new CultureInfo("sl-SI"); + + CultureInfo.CurrentUICulture = newUICulture; + Console.WriteLine("The current UI culture is now {0}", + CultureInfo.CurrentUICulture.Name); + } +} +// The example displays output like the following: +// The current UI culture is en-US +// The current UI culture is now sl-SI +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/current1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/current1.cs new file mode 100644 index 0000000000000..fe3a1587f5a9d --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/current1.cs @@ -0,0 +1,20 @@ +// +using System; +using System.Globalization; +using System.Threading; + +public class CurrentCultureEx +{ + public static void Main() + { + CultureInfo culture1 = CultureInfo.CurrentCulture; + CultureInfo culture2 = Thread.CurrentThread.CurrentCulture; + Console.WriteLine("The current culture is {0}", culture1.Name); + Console.WriteLine("The two CultureInfo objects are equal: {0}", + culture1 == culture2); + } +} +// The example displays output like the following: +// The current culture is en-US +// The two CultureInfo objects are equal: True +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/currentui1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/currentui1.cs new file mode 100644 index 0000000000000..82c3347a4d2cb --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/currentui1.cs @@ -0,0 +1,20 @@ +// +using System; +using System.Globalization; +using System.Threading; + +public class CurrentUIEx +{ + public static void Main() + { + CultureInfo uiCulture1 = CultureInfo.CurrentUICulture; + CultureInfo uiCulture2 = Thread.CurrentThread.CurrentUICulture; + Console.WriteLine("The current UI culture is {0}", uiCulture1.Name); + Console.WriteLine("The two CultureInfo objects are equal: {0}", + uiCulture1 == uiCulture2); + } +} +// The example displays output like the following: +// The current UI culture is en-US +// The two CultureInfo objects are equal: True +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/defaultthread1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/defaultthread1.cs new file mode 100644 index 0000000000000..9edecf6f2e45a --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/defaultthread1.cs @@ -0,0 +1,70 @@ +// +using System; +using System.Globalization; +using System.Threading; + +public class DefaultThreadEx +{ + static Random rnd = new Random(); + + public static void Main() + { + if (Thread.CurrentThread.CurrentCulture.Name != "fr-FR") + { + // If current culture is not fr-FR, set culture to fr-FR. + Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR"); + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("fr-FR"); + } + else + { + // Set culture to en-US. + Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US"); + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("en-US"); + } + ThreadProc(); + + Thread worker = new Thread(ThreadProc); + worker.Name = "WorkerThread"; + worker.Start(); + } + + private static void DisplayThreadInfo() + { + Console.WriteLine("\nCurrent Thread Name: '{0}'", + Thread.CurrentThread.Name); + Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}", + Thread.CurrentThread.CurrentCulture.Name, + Thread.CurrentThread.CurrentUICulture.Name); + } + + private static void DisplayValues() + { + // Create new thread and display three random numbers. + Console.WriteLine("Some currency values:"); + for (int ctr = 0; ctr <= 3; ctr++) + Console.WriteLine(" {0:C2}", rnd.NextDouble() * 10); + } + + private static void ThreadProc() + { + DisplayThreadInfo(); + DisplayValues(); + } +} +// The example displays output similar to the following: +// Current Thread Name: '' +// Current Thread Culture/UI Culture: fr-FR/fr-FR +// Some currency values: +// 8,11 € +// 1,48 € +// 8,99 € +// 9,04 € +// +// Current Thread Name: 'WorkerThread' +// Current Thread Culture/UI Culture: en-US/en-US +// Some currency values: +// $6.72 +// $6.35 +// $2.90 +// $7.72 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/getcultures1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/getcultures1.cs new file mode 100644 index 0000000000000..9b876f3d32c4a --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/getcultures1.cs @@ -0,0 +1,44 @@ +// +using System; +using System.Globalization; + +public class GetCulturesEx +{ + public static void Main() + { + // Get all custom cultures. + CultureInfo[] custom = CultureInfo.GetCultures(CultureTypes.UserCustomCulture); + if (custom.Length == 0) + { + Console.WriteLine("There are no user-defined custom cultures."); + } + else + { + Console.WriteLine("Custom cultures:"); + foreach (var culture in custom) + Console.WriteLine(" {0} -- {1}", culture.Name, culture.DisplayName); + } + Console.WriteLine(); + + // Get all replacement cultures. + CultureInfo[] replacements = CultureInfo.GetCultures(CultureTypes.ReplacementCultures); + if (replacements.Length == 0) + { + Console.WriteLine("There are no replacement cultures."); + } + else + { + Console.WriteLine("Replacement cultures:"); + foreach (var culture in replacements) + Console.WriteLine(" {0} -- {1}", culture.Name, culture.DisplayName); + } + Console.WriteLine(); + } +} +// The example displays output like the following: +// Custom cultures: +// x-en-US-sample -- English (United States) +// fj-FJ -- Boumaa Fijian (Viti) +// +// There are no replacement cultures. +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/project.csproj b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/project.csproj new file mode 100644 index 0000000000000..2508cb7fae22e --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/project.csproj @@ -0,0 +1,8 @@ + + + + Library + net481 + + + diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/setthreads1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/setthreads1.cs new file mode 100644 index 0000000000000..2d0eede894a5f --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/CultureInfo/csharp/setthreads1.cs @@ -0,0 +1,70 @@ +// +using System; +using System.Globalization; +using System.Threading; + +public class SetThreadsEx +{ + static Random rnd = new Random(); + + public static void Main() + { + if (Thread.CurrentThread.CurrentCulture.Name != "fr-FR") + { + // If current culture is not fr-FR, set culture to fr-FR. + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR"); + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("fr-FR"); + } + else + { + // Set culture to en-US. + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("en-US"); + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("en-US"); + } + ThreadProc(); + + Thread worker = new Thread(SetThreadsEx.ThreadProc); + worker.Name = "WorkerThread"; + worker.Start(); + } + + private static void DisplayThreadInfo() + { + Console.WriteLine("\nCurrent Thread Name: '{0}'", + Thread.CurrentThread.Name); + Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}", + Thread.CurrentThread.CurrentCulture.Name, + Thread.CurrentThread.CurrentUICulture.Name); + } + + private static void DisplayValues() + { + // Create new thread and display three random numbers. + Console.WriteLine("Some currency values:"); + for (int ctr = 0; ctr <= 3; ctr++) + Console.WriteLine(" {0:C2}", rnd.NextDouble() * 10); + } + + private static void ThreadProc() + { + DisplayThreadInfo(); + DisplayValues(); + } +} +// The example displays output similar to the following: +// Current Thread Name: '' +// Current Thread Culture/UI Culture: fr-FR/fr-FR +// Some currency values: +// 6,83 € +// 3,47 € +// 6,07 € +// 1,70 € +// +// Current Thread Name: 'WorkerThread' +// Current Thread Culture/UI Culture: fr-FR/fr-FR +// Some currency values: +// 9,54 € +// 9,50 € +// 0,58 € +// 6,91 € +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/create1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/create1.cs new file mode 100644 index 0000000000000..12d26afd04c38 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/create1.cs @@ -0,0 +1,112 @@ +using System; + +public class Example +{ + public static void Main() + { + CreateInvariant1(); + Console.WriteLine(); + CreateNeutral2(); + Console.WriteLine(); + CreateSpecific3(); + } + + private static void CreateInvariant1() + { + // + System.Globalization.DateTimeFormatInfo dtfi; + + dtfi = System.Globalization.DateTimeFormatInfo.InvariantInfo; + Console.WriteLine(dtfi.IsReadOnly); + + dtfi = new System.Globalization.DateTimeFormatInfo(); + Console.WriteLine(dtfi.IsReadOnly); + + dtfi = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat; + Console.WriteLine(dtfi.IsReadOnly); + // The example displays the following output: + // True + // False + // True + // + } + + private static void CreateNeutral2() + { + // + System.Globalization.CultureInfo specific, neutral; + System.Globalization.DateTimeFormatInfo dtfi; + + // Instantiate a culture by creating a specific culture and using its Parent property. + specific = System.Globalization.CultureInfo.GetCultureInfo("fr-FR"); + neutral = specific.Parent; + dtfi = neutral.DateTimeFormat; + Console.WriteLine("{0} from Parent property: {1}", neutral.Name, dtfi.IsReadOnly); + + dtfi = System.Globalization.CultureInfo.GetCultureInfo("fr-FR").Parent.DateTimeFormat; + Console.WriteLine("{0} from Parent property: {1}", neutral.Name, dtfi.IsReadOnly); + + // Instantiate a neutral culture using the CultureInfo constructor. + neutral = new System.Globalization.CultureInfo("fr"); + dtfi = neutral.DateTimeFormat; + Console.WriteLine("{0} from CultureInfo constructor: {1}", neutral.Name, dtfi.IsReadOnly); + + // Instantiate a culture using CreateSpecificCulture. + neutral = System.Globalization.CultureInfo.CreateSpecificCulture("fr"); + dtfi = neutral.DateTimeFormat; + Console.WriteLine("{0} from CreateSpecificCulture: {1}", neutral.Name, dtfi.IsReadOnly); + + // Retrieve a culture by calling the GetCultureInfo method. + neutral = System.Globalization.CultureInfo.GetCultureInfo("fr"); + dtfi = neutral.DateTimeFormat; + Console.WriteLine("{0} from GetCultureInfo: {1}", neutral.Name, dtfi.IsReadOnly); + + // Instantiate a DateTimeFormatInfo object by calling GetInstance. + neutral = System.Globalization.CultureInfo.CreateSpecificCulture("fr"); + dtfi = System.Globalization.DateTimeFormatInfo.GetInstance(neutral); + Console.WriteLine("{0} from GetInstance: {1}", neutral.Name, dtfi.IsReadOnly); + + // The example displays the following output: + // fr from Parent property: False + // fr from Parent property: False + // fr from CultureInfo constructor: False + // fr-FR from CreateSpecificCulture: False + // fr from GetCultureInfo: True + // fr-FR from GetInstance: False + // + } + + private static void CreateSpecific3() + { + // + System.Globalization.CultureInfo ci = null; + System.Globalization.DateTimeFormatInfo dtfi = null; + + // Instantiate a culture using CreateSpecificCulture. + ci = System.Globalization.CultureInfo.CreateSpecificCulture("en-US"); + dtfi = ci.DateTimeFormat; + Console.WriteLine("{0} from CreateSpecificCulture: {1}", ci.Name, dtfi.IsReadOnly); + + // Instantiate a culture using the CultureInfo constructor. + ci = new System.Globalization.CultureInfo("en-CA"); + dtfi = ci.DateTimeFormat; + Console.WriteLine("{0} from CultureInfo constructor: {1}", ci.Name, dtfi.IsReadOnly); + + // Retrieve a culture by calling the GetCultureInfo method. + ci = System.Globalization.CultureInfo.GetCultureInfo("en-AU"); + dtfi = ci.DateTimeFormat; + Console.WriteLine("{0} from GetCultureInfo: {1}", ci.Name, dtfi.IsReadOnly); + + // Instantiate a DateTimeFormatInfo object by calling DateTimeFormatInfo.GetInstance. + ci = System.Globalization.CultureInfo.CreateSpecificCulture("en-GB"); + dtfi = System.Globalization.DateTimeFormatInfo.GetInstance(ci); + Console.WriteLine("{0} from GetInstance: {1}", ci.Name, dtfi.IsReadOnly); + + // The example displays the following output: + // en-US from CreateSpecificCulture: False + // en-CA from CultureInfo constructor: False + // en-AU from GetCultureInfo: True + // en-GB from GetInstance: False + // + } +} diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/create2.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/create2.cs new file mode 100644 index 0000000000000..01e02d14e15c0 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/create2.cs @@ -0,0 +1,25 @@ +using System; +using System.Globalization; + +public class Create2Ex +{ + public static void Main() + { + // + DateTimeFormatInfo dtfi; + + dtfi = DateTimeFormatInfo.CurrentInfo; + Console.WriteLine(dtfi.IsReadOnly); + + dtfi = CultureInfo.CurrentCulture.DateTimeFormat; + Console.WriteLine(dtfi.IsReadOnly); + + dtfi = DateTimeFormatInfo.GetInstance(CultureInfo.CurrentCulture); + Console.WriteLine(dtfi.IsReadOnly); + // The example displays the following output: + // True + // True + // True + // + } +} diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example1.cs new file mode 100644 index 0000000000000..04262e40ad837 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example1.cs @@ -0,0 +1,30 @@ +// +using System; +using System.Globalization; + +public class Example1 +{ + public static void Main() + { + DateTime dateValue = new DateTime(2013, 8, 18); + CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US"); + DateTimeFormatInfo dtfi = enUS.DateTimeFormat; + + Console.WriteLine("Before modifying DateTimeFormatInfo object: "); + Console.WriteLine("{0}: {1}\n", dtfi.ShortDatePattern, + dateValue.ToString("d", enUS)); + + // Modify the short date pattern. + dtfi.ShortDatePattern = "yyyy-MM-dd"; + Console.WriteLine("After modifying DateTimeFormatInfo object: "); + Console.WriteLine("{0}: {1}", dtfi.ShortDatePattern, + dateValue.ToString("d", enUS)); + } +} +// The example displays the following output: +// Before modifying DateTimeFormatInfo object: +// M/d/yyyy: 8/18/2013 +// +// After modifying DateTimeFormatInfo object: +// yyyy-MM-dd: 2013-08-18 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example2.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example2.cs new file mode 100644 index 0000000000000..6f4e5ddea758d --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example2.cs @@ -0,0 +1,39 @@ +// +using System; +using System.Globalization; + +public class Example2 +{ + public static void Main() + { + DateTime value = new DateTime(2013, 7, 9); + CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US"); + DateTimeFormatInfo dtfi = enUS.DateTimeFormat; + String[] formats = { "D", "F", "f" }; + + // Display date before modifying properties. + foreach (var fmt in formats) + Console.WriteLine("{0}: {1}", fmt, value.ToString(fmt, dtfi)); + + Console.WriteLine(); + + // We don't want to change the FullDateTimePattern, so we need to save it. + String originalFullDateTimePattern = dtfi.FullDateTimePattern; + + // Modify day name abbreviations and long date pattern. + dtfi.AbbreviatedDayNames = new String[] { "Su", "M", "Tu", "W", "Th", "F", "Sa" }; + dtfi.LongDatePattern = "ddd dd-MMM-yyyy"; + dtfi.FullDateTimePattern = originalFullDateTimePattern; + foreach (var fmt in formats) + Console.WriteLine("{0}: {1}", fmt, value.ToString(fmt, dtfi)); + } +} +// The example displays the following output: +// D: Tuesday, July 9, 2013 +// F: Tuesday, July 9, 2013 12:00:00 AM +// f: Tuesday, July 9, 2013 12:00 AM +// +// D: Tu 09-Jul-2013 +// F: Tuesday, July 9, 2013 12:00:00 AM +// f: Tu 09-Jul-2013 12:00 AM +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example3.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example3.cs new file mode 100644 index 0000000000000..5f78c7499ddbc --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example3.cs @@ -0,0 +1,25 @@ +// +using System; +using System.Globalization; + +public class Example3 +{ + public static void Main() + { + DateTime dateValue = new DateTime(2013, 08, 28); + CultureInfo frFR = CultureInfo.CreateSpecificCulture("fr-FR"); + DateTimeFormatInfo dtfi = frFR.DateTimeFormat; + + Console.WriteLine("Before modifying DateSeparator property: {0}", + dateValue.ToString("g", frFR)); + + // Modify the date separator. + dtfi.DateSeparator = "-"; + Console.WriteLine("After modifying the DateSeparator property: {0}", + dateValue.ToString("g", frFR)); + } +} +// The example displays the following output: +// Before modifying DateSeparator property: 28/08/2013 00:00 +// After modifying the DateSeparator property: 28-08-2013 00:00 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example4.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example4.cs new file mode 100644 index 0000000000000..14f4fc8140451 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example4.cs @@ -0,0 +1,47 @@ +// +using System; +using System.Globalization; + +public class Example4 +{ + public static void Main() + { + DateTime dateValue = new DateTime(2013, 5, 18, 13, 30, 0); + String[] formats = { "D", "f", "F" }; + + CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US"); + DateTimeFormatInfo dtfi = enUS.DateTimeFormat; + String originalLongDatePattern = dtfi.LongDatePattern; + + // Display the default form of three long date formats. + foreach (var fmt in formats) + Console.WriteLine(dateValue.ToString(fmt, dtfi)); + + Console.WriteLine(); + + // Modify the long date pattern. + dtfi.LongDatePattern = originalLongDatePattern + " g"; + foreach (var fmt in formats) + Console.WriteLine(dateValue.ToString(fmt, dtfi)); + + Console.WriteLine(); + + // Change A.D. to C.E. (for Common Era) + dtfi.LongDatePattern = originalLongDatePattern + @" 'C.E.'"; + foreach (var fmt in formats) + Console.WriteLine(dateValue.ToString(fmt, dtfi)); + } +} +// The example displays the following output: +// Saturday, May 18, 2013 +// Saturday, May 18, 2013 1:30 PM +// Saturday, May 18, 2013 1:30:00 PM +// +// Saturday, May 18, 2013 A.D. +// Saturday, May 18, 2013 A.D. 1:30 PM +// Saturday, May 18, 2013 A.D. 1:30:00 PM +// +// Saturday, May 18, 2013 C.E. +// Saturday, May 18, 2013 C.E. 1:30 PM +// Saturday, May 18, 2013 C.E. 1:30:00 PM +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example5.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example5.cs new file mode 100644 index 0000000000000..e23c4454dad1b --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/example5.cs @@ -0,0 +1,47 @@ +// +using System; +using System.Globalization; +using System.Text.RegularExpressions; + +public class Example5 +{ + public static void Main() + { + CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US"); + DateTimeFormatInfo dtfi = enUS.DateTimeFormat; + + Console.WriteLine("Original Property Values:"); + Console.WriteLine("ShortTimePattern: " + dtfi.ShortTimePattern); + Console.WriteLine("LongTimePattern: " + dtfi.LongTimePattern); + Console.WriteLine("FullDateTimePattern: " + dtfi.FullDateTimePattern); + Console.WriteLine(); + + dtfi.LongTimePattern = ReplaceWith24HourClock(dtfi.LongTimePattern); + dtfi.ShortTimePattern = ReplaceWith24HourClock(dtfi.ShortTimePattern); + + Console.WriteLine("Modififed Property Values:"); + Console.WriteLine("ShortTimePattern: " + dtfi.ShortTimePattern); + Console.WriteLine("LongTimePattern: " + dtfi.LongTimePattern); + Console.WriteLine("FullDateTimePattern: " + dtfi.FullDateTimePattern); + } + + private static string ReplaceWith24HourClock(string fmt) + { + string pattern = @"^(?\s*t+\s*)? " + + @"(?(openAMPM) h+(?[^ht]+)$ " + + @"| \s*h+(?[^ht]+)\s*t+)"; + return Regex.Replace(fmt, pattern, "HH${nonHours}", + RegexOptions.IgnorePatternWhitespace); + } +} +// The example displays the following output: +// Original Property Values: +// ShortTimePattern: h:mm tt +// LongTimePattern: h:mm:ss tt +// FullDateTimePattern: dddd, MMMM dd, yyyy h:mm:ss tt +// +// Modififed Property Values: +// ShortTimePattern: HH:mm +// LongTimePattern: HH:mm:ss +// FullDateTimePattern: dddd, MMMM dd, yyyy HH:mm:ss +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/formatprovider1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/formatprovider1.cs new file mode 100644 index 0000000000000..e555bf7ba6862 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/formatprovider1.cs @@ -0,0 +1,43 @@ +// +using System; +using System.Globalization; + +public class CurrentCultureFormatProvider : IFormatProvider +{ + public Object GetFormat(Type formatType) + { + Console.WriteLine("Requesting an object of type {0}", + formatType.Name); + if (formatType == typeof(NumberFormatInfo)) + return NumberFormatInfo.CurrentInfo; + else if (formatType == typeof(DateTimeFormatInfo)) + return DateTimeFormatInfo.CurrentInfo; + else + return null; + } +} + +public class FormatProviderEx1 +{ + public static void Main() + { + DateTime dateValue = new DateTime(2013, 5, 28, 13, 30, 0); + string value = dateValue.ToString("F", new CurrentCultureFormatProvider()); + Console.WriteLine(value); + Console.WriteLine(); + string composite = String.Format(new CurrentCultureFormatProvider(), + "Date: {0:d} Amount: {1:C} Description: {2}", + dateValue, 1264.03m, "Service Charge"); + Console.WriteLine(composite); + Console.WriteLine(); + } +} +// The example displays output like the following: +// Requesting an object of type DateTimeFormatInfo +// Tuesday, May 28, 2013 1:30:00 PM +// +// Requesting an object of type ICustomFormatter +// Requesting an object of type DateTimeFormatInfo +// Requesting an object of type NumberFormatInfo +// Date: 5/28/2013 Amount: $1,264.03 Description: Service Charge +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate2.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate2.cs new file mode 100644 index 0000000000000..fde2e0a0c06aa --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate2.cs @@ -0,0 +1,21 @@ +// +using System; +using System.Globalization; + +public class InstantiateEx1 +{ + public static void Main() + { + DateTimeFormatInfo current1 = DateTimeFormatInfo.CurrentInfo; + current1 = (DateTimeFormatInfo)current1.Clone(); + Console.WriteLine(current1.IsReadOnly); + + CultureInfo culture2 = CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name); + DateTimeFormatInfo current2 = culture2.DateTimeFormat; + Console.WriteLine(current2.IsReadOnly); + } +} +// The example displays the following output: +// False +// False +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate3.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate3.cs new file mode 100644 index 0000000000000..50f450e2a8057 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate3.cs @@ -0,0 +1,32 @@ +// +using System; +using System.Globalization; + +public class InstantiateEx3 +{ + public static void Main() + { + CultureInfo culture; + DateTimeFormatInfo dtfi; + + culture = CultureInfo.CurrentCulture; + dtfi = culture.DateTimeFormat; + Console.WriteLine("Culture Name: {0}", culture.Name); + Console.WriteLine("User Overrides: {0}", culture.UseUserOverride); + Console.WriteLine("Long Time Pattern: {0}\n", culture.DateTimeFormat.LongTimePattern); + + culture = new CultureInfo(CultureInfo.CurrentCulture.Name, false); + Console.WriteLine("Culture Name: {0}", culture.Name); + Console.WriteLine("User Overrides: {0}", culture.UseUserOverride); + Console.WriteLine("Long Time Pattern: {0}\n", culture.DateTimeFormat.LongTimePattern); + } +} +// The example displays the following output: +// Culture Name: en-US +// User Overrides: True +// Long Time Pattern: HH:mm:ss +// +// Culture Name: en-US +// User Overrides: False +// Long Time Pattern: h:mm:ss tt +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate6.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate6.cs new file mode 100644 index 0000000000000..8f599ce580688 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate6.cs @@ -0,0 +1,120 @@ +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Reflection; + +public class InstantiateEx6 +{ + public static void Main() + { + // Get all the neutral cultures + List names = new List(); + Array.ForEach(CultureInfo.GetCultures(CultureTypes.NeutralCultures), + culture => names.Add(culture.Name)); + names.Sort(); + foreach (var name in names) + { + // Ignore the invariant culture. + if (name == "") continue; + + ListSimilarChildCultures(name); + } + } + + private static void ListSimilarChildCultures(String name) + { + // Create the neutral DateTimeFormatInfo object. + DateTimeFormatInfo dtfi = CultureInfo.GetCultureInfo(name).DateTimeFormat; + // Retrieve all specific cultures of the neutral culture. + CultureInfo[] cultures = Array.FindAll(CultureInfo.GetCultures(CultureTypes.SpecificCultures), + culture => culture.Name.StartsWith(name + "-", StringComparison.OrdinalIgnoreCase)); + // Create an array of DateTimeFormatInfo properties + PropertyInfo[] properties = typeof(DateTimeFormatInfo).GetProperties(BindingFlags.Instance | BindingFlags.Public); + bool hasOneMatch = false; + + foreach (var ci in cultures) + { + bool match = true; + // Get the DateTimeFormatInfo for a specific culture. + DateTimeFormatInfo specificDtfi = ci.DateTimeFormat; + // Compare the property values of the two. + foreach (var prop in properties) + { + // We're not interested in the value of IsReadOnly. + if (prop.Name == "IsReadOnly") continue; + + // For arrays, iterate the individual elements to see if they are the same. + if (prop.PropertyType.IsArray) + { + IList nList = (IList)prop.GetValue(dtfi, null); + IList sList = (IList)prop.GetValue(specificDtfi, null); + if (nList.Count != sList.Count) + { + match = false; + Console.WriteLine(" Different n in {2} array for {0} and {1}", name, ci.Name, prop.Name); + break; + } + + for (int ctr = 0; ctr < nList.Count; ctr++) + { + if (!nList[ctr].Equals(sList[ctr])) + { + match = false; + Console.WriteLine(" {0} value different for {1} and {2}", prop.Name, name, ci.Name); + break; + } + } + + if (!match) break; + } + // Get non-array values. + else + { + Object specificValue = prop.GetValue(specificDtfi); + Object neutralValue = prop.GetValue(dtfi); + + // Handle comparison of Calendar objects. + if (prop.Name == "Calendar") + { + // The cultures have a different calendar type. + if (specificValue.ToString() != neutralValue.ToString()) + { + Console.WriteLine(" Different calendar types for {0} and {1}", name, ci.Name); + match = false; + break; + } + + if (specificValue is GregorianCalendar) + { + if (((GregorianCalendar)specificValue).CalendarType != ((GregorianCalendar)neutralValue).CalendarType) + { + Console.WriteLine(" Different Gregorian calendar types for {0} and {1}", name, ci.Name); + match = false; + break; + } + } + } + else if (!specificValue.Equals(neutralValue)) + { + match = false; + Console.WriteLine(" Different {0} values for {1} and {2}", prop.Name, name, ci.Name); + break; + } + } + } + if (match) + { + Console.WriteLine("DateTimeFormatInfo object for '{0}' matches '{1}'", + name, ci.Name); + hasOneMatch = true; + } + } + if (!hasOneMatch) + Console.WriteLine("DateTimeFormatInfo object for '{0}' --> No Match", name); + + Console.WriteLine(); + } +} +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/parse1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/parse1.cs new file mode 100644 index 0000000000000..4b3502d2c4002 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/parse1.cs @@ -0,0 +1,46 @@ +// +using System; +using System.Globalization; + +public class ParseEx1 +{ + public static void Main() + { + string[] dateStrings = { "08/18/2014", "01/02/2015" }; + string[] cultureNames = { "en-US", "en-GB", "fr-FR", "fi-FI" }; + + foreach (var cultureName in cultureNames) + { + CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName); + Console.WriteLine("Parsing strings using the {0} culture.", + culture.Name); + foreach (var dateStr in dateStrings) + { + try + { + Console.WriteLine(String.Format(culture, + " '{0}' --> {1:D}", dateStr, + DateTime.Parse(dateStr, culture))); + } + catch (FormatException) + { + Console.WriteLine(" Unable to parse '{0}'", dateStr); + } + } + } + } +} +// The example displays the following output: +// Parsing strings using the en-US culture. +// '08/18/2014' --> Monday, August 18, 2014 +// '01/02/2015' --> Friday, January 02, 2015 +// Parsing strings using the en-GB culture. +// Unable to parse '08/18/2014' +// '01/02/2015' --> 01 February 2015 +// Parsing strings using the fr-FR culture. +// Unable to parse '08/18/2014' +// '01/02/2015' --> dimanche 1 février 2015 +// Parsing strings using the fi-FI culture. +// Unable to parse '08/18/2014' +// '01/02/2015' --> 1. helmikuuta 2015 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/parse2.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/parse2.cs new file mode 100644 index 0000000000000..05097bec5880d --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/parse2.cs @@ -0,0 +1,38 @@ +// +using System; +using System.Globalization; + +public class ParseEx2 +{ + public static void Main() + { + string inputDate = "14/05/10"; + + CultureInfo[] cultures = { CultureInfo.GetCultureInfo("en-US"), + CultureInfo.CreateSpecificCulture("en-US") }; + + foreach (var culture in cultures) + { + try + { + Console.WriteLine("{0} culture reflects user overrides: {1}", + culture.Name, culture.UseUserOverride); + DateTime occasion = DateTime.Parse(inputDate, culture); + Console.WriteLine("'{0}' --> {1}", inputDate, + occasion.ToString("D", CultureInfo.InvariantCulture)); + } + catch (FormatException) + { + Console.WriteLine("Unable to parse '{0}'", inputDate); + } + Console.WriteLine(); + } + } +} +// The example displays the following output: +// en-US culture reflects user overrides: False +// Unable to parse '14/05/10' +// +// en-US culture reflects user overrides: True +// '14/05/10' --> Saturday, 10 May 2014 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/project.csproj b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/project.csproj new file mode 100644 index 0000000000000..410c4a67f2207 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/project.csproj @@ -0,0 +1,9 @@ + + + + Library + net8.0 + enable + + + diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize1.cs new file mode 100644 index 0000000000000..ecd092ff9e766 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize1.cs @@ -0,0 +1,30 @@ +// +using System; +using System.Globalization; +using System.IO; + +public class SerializeEx1 +{ + public static void Main() + { + StreamWriter sw = new StreamWriter(@".\DateData.dat"); + // Define a date and time to serialize. + DateTime originalDate = new DateTime(2014, 08, 18, 08, 16, 35); + // Display information on the date and time. + Console.WriteLine("Date to serialize: {0:F}", originalDate); + Console.WriteLine("Current Culture: {0}", + CultureInfo.CurrentCulture.Name); + Console.WriteLine("Time Zone: {0}", + TimeZoneInfo.Local.DisplayName); + // Convert the date value to UTC. + DateTime utcDate = originalDate.ToUniversalTime(); + // Serialize the UTC value. + sw.Write(utcDate.ToString("o", DateTimeFormatInfo.InvariantInfo)); + sw.Close(); + } +} +// The example displays the following output: +// Date to serialize: Monday, August 18, 2014 8:16:35 AM +// Current Culture: en-US +// Time Zone: (UTC-08:00) Pacific Time (US & Canada) +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize2.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize2.cs new file mode 100644 index 0000000000000..8798f411bcfd0 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize2.cs @@ -0,0 +1,31 @@ +// +using System; +using System.Globalization; +using System.IO; + +public class SerializeEx2 +{ + public static void Main() + { + // Open the file and retrieve the date string. + StreamReader sr = new StreamReader(@".\DateData.dat"); + String dateValue = sr.ReadToEnd(); + + // Parse the date. + DateTime parsedDate = DateTime.ParseExact(dateValue, "o", + DateTimeFormatInfo.InvariantInfo); + // Convert it to local time. + DateTime restoredDate = parsedDate.ToLocalTime(); + // Display information on the date and time. + Console.WriteLine("Deserialized date: {0:F}", restoredDate); + Console.WriteLine("Current Culture: {0}", + CultureInfo.CurrentCulture.Name); + Console.WriteLine("Time Zone: {0}", + TimeZoneInfo.Local.DisplayName); + } +} +// The example displays the following output: +// Deserialized date: lundi 18 août 2014 17:16:35 +// Current Culture: fr-FR +// Time Zone: (UTC+01:00) Brussels, Copenhagen, Madrid, Paris +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/customize_currency1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/customize_currency1.cs new file mode 100644 index 0000000000000..1e5cb5579d2fc --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/customize_currency1.cs @@ -0,0 +1,42 @@ +// +using System; +using System.Globalization; + +public class Example +{ + public static void Main() + { + // Retrieve a writable NumberFormatInfo object. + CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US"); + NumberFormatInfo nfi = enUS.NumberFormat; + + // Use the ISO currency symbol instead of the native currency symbol. + nfi.CurrencySymbol = (new RegionInfo(enUS.Name)).ISOCurrencySymbol; + // Change the positive currency pattern to . + nfi.CurrencyPositivePattern = 2; + // Change the negative currency pattern to . + nfi.CurrencyNegativePattern = 12; + + // Produce the result strings by calling ToString. + Decimal[] values = { 1065.23m, 19.89m, -.03m, -175902.32m }; + foreach (var value in values) + Console.WriteLine(value.ToString("C", enUS)); + + Console.WriteLine(); + + // Produce the result strings by calling a composite formatting method. + foreach (var value in values) + Console.WriteLine(String.Format(enUS, "{0:C}", value)); + } +} +// The example displays the following output: +// USD 1,065.23 +// USD 19.89 +// USD -0.03 +// USD -175,902.32 +// +// USD 1,065.23 +// USD 19.89 +// USD -0.03 +// USD -175,902.32 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/customize_ssn1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/customize_ssn1.cs new file mode 100644 index 0000000000000..1e91cac484a24 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/customize_ssn1.cs @@ -0,0 +1,37 @@ +// +using System; +using System.Globalization; + +public class CustomizeSSNEx +{ + public static void Main() + { + // Instantiate a read-only NumberFormatInfo object. + CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US"); + NumberFormatInfo nfi = enUS.NumberFormat; + + // Modify the relevant properties. + nfi.NumberGroupSeparator = "-"; + nfi.NumberGroupSizes = new int[] { 3, 2, 4 }; + nfi.NumberDecimalDigits = 0; + + int[] ids = { 111223333, 999776666 }; + + // Produce the result string by calling ToString. + foreach (var id in ids) + Console.WriteLine(id.ToString("N", enUS)); + + Console.WriteLine(); + + // Produce the result string using composite formatting. + foreach (var id in ids) + Console.WriteLine(String.Format(enUS, "{0:N}", id)); + } +} +// The example displays the following output: +// 1112-23-333 +// 9997-76-666 +// +// 1112-23-333 +// 9997-76-666 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/formatprovider1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/formatprovider1.cs new file mode 100644 index 0000000000000..cdf2540b45c48 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/formatprovider1.cs @@ -0,0 +1,43 @@ +// +using System; +using System.Globalization; + +public class CurrentCultureFormatProvider : IFormatProvider +{ + public Object GetFormat(Type formatType) + { + Console.WriteLine("Requesting an object of type {0}", + formatType.Name); + if (formatType == typeof(NumberFormatInfo)) + return NumberFormatInfo.CurrentInfo; + else if (formatType == typeof(DateTimeFormatInfo)) + return DateTimeFormatInfo.CurrentInfo; + else + return null; + } +} + +public class FormatProviderEx +{ + public static void Main() + { + Decimal amount = 1203.541m; + string value = amount.ToString("C2", new CurrentCultureFormatProvider()); + Console.WriteLine(value); + Console.WriteLine(); + string composite = String.Format(new CurrentCultureFormatProvider(), + "Date: {0} Amount: {1} Description: {2}", + DateTime.Now, 1264.03m, "Service Charge"); + Console.WriteLine(composite); + Console.WriteLine(); + } +} +// The example displays output like the following: +// Requesting an object of type NumberFormatInfo +// $1,203.54 +// +// Requesting an object of type ICustomFormatter +// Requesting an object of type DateTimeFormatInfo +// Requesting an object of type NumberFormatInfo +// Date: 11/15/2012 2:00:01 PM Amount: 1264.03 Description: Service Charge +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate1.cs new file mode 100644 index 0000000000000..9f1517d5dadcd --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate1.cs @@ -0,0 +1,23 @@ +// +using System; +using System.Globalization; + +public class InstantiateEx1 +{ + public static void Main() + { + NumberFormatInfo current1 = CultureInfo.CurrentCulture.NumberFormat; + Console.WriteLine(current1.IsReadOnly); + + NumberFormatInfo current2 = NumberFormatInfo.CurrentInfo; + Console.WriteLine(current2.IsReadOnly); + + NumberFormatInfo current3 = NumberFormatInfo.GetInstance(CultureInfo.CurrentCulture); + Console.WriteLine(current3.IsReadOnly); + } +} +// The example displays the following output: +// True +// True +// True +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate2.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate2.cs new file mode 100644 index 0000000000000..940e39567844f --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate2.cs @@ -0,0 +1,21 @@ +// +using System; +using System.Globalization; + +public class InstantiateEx2 +{ + public static void Main() + { + NumberFormatInfo current1 = NumberFormatInfo.CurrentInfo; + current1 = (NumberFormatInfo)current1.Clone(); + Console.WriteLine(current1.IsReadOnly); + + CultureInfo culture2 = CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name); + NumberFormatInfo current2 = culture2.NumberFormat; + Console.WriteLine(current2.IsReadOnly); + } +} +// The example displays the following output: +// False +// False +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate3.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate3.cs new file mode 100644 index 0000000000000..9f823b693991f --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate3.cs @@ -0,0 +1,32 @@ +// +using System; +using System.Globalization; + +public class InstantiateEx3 +{ + public static void Main() + { + CultureInfo culture; + NumberFormatInfo nfi; + + culture = CultureInfo.CurrentCulture; + nfi = culture.NumberFormat; + Console.WriteLine("Culture Name: {0}", culture.Name); + Console.WriteLine("User Overrides: {0}", culture.UseUserOverride); + Console.WriteLine("Currency Symbol: {0}\n", culture.NumberFormat.CurrencySymbol); + + culture = new CultureInfo(CultureInfo.CurrentCulture.Name, false); + Console.WriteLine("Culture Name: {0}", culture.Name); + Console.WriteLine("User Overrides: {0}", culture.UseUserOverride); + Console.WriteLine("Currency Symbol: {0}", culture.NumberFormat.CurrencySymbol); + } +} +// The example displays the following output: +// Culture Name: en-US +// User Overrides: True +// Currency Symbol: USD +// +// Culture Name: en-US +// User Overrides: False +// Currency Symbol: $ +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate4.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate4.cs new file mode 100644 index 0000000000000..6156482cc1f39 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate4.cs @@ -0,0 +1,25 @@ +// +using System; +using System.Globalization; + +public class InstantiateEx4 +{ + public static void Main() + { + NumberFormatInfo nfi; + + nfi = System.Globalization.NumberFormatInfo.InvariantInfo; + Console.WriteLine(nfi.IsReadOnly); + + nfi = CultureInfo.InvariantCulture.NumberFormat; + Console.WriteLine(nfi.IsReadOnly); + + nfi = new NumberFormatInfo(); + Console.WriteLine(nfi.IsReadOnly); + } +} +// The example displays the following output: +// True +// True +// False +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate5.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate5.cs new file mode 100644 index 0000000000000..2e4704eeb08f1 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate5.cs @@ -0,0 +1,33 @@ +// +using System; +using System.Globalization; + +public class InstantiateEx5 +{ + public static void Main() + { + CultureInfo culture; + NumberFormatInfo nfi; + + nfi = CultureInfo.GetCultureInfo("id-ID").NumberFormat; + Console.WriteLine("Read-only: {0}", nfi.IsReadOnly); + + culture = new CultureInfo("id-ID"); + nfi = NumberFormatInfo.GetInstance(culture); + Console.WriteLine("Read-only: {0}", nfi.IsReadOnly); + + culture = CultureInfo.CreateSpecificCulture("id-ID"); + nfi = culture.NumberFormat; + Console.WriteLine("Read-only: {0}", nfi.IsReadOnly); + + culture = new CultureInfo("id-ID"); + nfi = culture.NumberFormat; + Console.WriteLine("Read-only: {0}", nfi.IsReadOnly); + } +} +// The example displays the following output: +// Read-only: True +// Read-only: False +// Read-only: False +// Read-only: False +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate6.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate6.cs new file mode 100644 index 0000000000000..6b8bccaa8fbab --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/instantiate6.cs @@ -0,0 +1,87 @@ +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Reflection; + +public class InstantiateEx6 +{ + public static void Main() + { + // Get all the neutral cultures + List names = new List(); + Array.ForEach(CultureInfo.GetCultures(CultureTypes.NeutralCultures), + culture => names.Add(culture.Name)); + names.Sort(); + foreach (var name in names) + { + // Ignore the invariant culture. + if (name == "") continue; + + ListSimilarChildCultures(name); + } + } + + private static void ListSimilarChildCultures(string name) + { + // Create the neutral NumberFormatInfo object. + NumberFormatInfo nfi = CultureInfo.GetCultureInfo(name).NumberFormat; + // Retrieve all specific cultures of the neutral culture. + CultureInfo[] cultures = Array.FindAll(CultureInfo.GetCultures(CultureTypes.SpecificCultures), + culture => culture.Name.StartsWith(name + "-", StringComparison.OrdinalIgnoreCase)); + // Create an array of NumberFormatInfo properties + PropertyInfo[] properties = typeof(NumberFormatInfo).GetProperties(BindingFlags.Instance | BindingFlags.Public); + bool hasOneMatch = false; + + foreach (var ci in cultures) + { + bool match = true; + // Get the NumberFormatInfo for a specific culture. + NumberFormatInfo specificNfi = ci.NumberFormat; + // Compare the property values of the two. + foreach (var prop in properties) + { + // We're not interested in the value of IsReadOnly. + if (prop.Name == "IsReadOnly") continue; + + // For arrays, iterate the individual elements to see if they are the same. + if (prop.PropertyType.IsArray) + { + IList nList = (IList)prop.GetValue(nfi, null); + IList sList = (IList)prop.GetValue(specificNfi, null); + if (nList.Count != sList.Count) + { + match = false; + break; + } + + for (int ctr = 0; ctr < nList.Count; ctr++) + { + if (!nList[ctr].Equals(sList[ctr])) + { + match = false; + break; + } + } + } + else if (!prop.GetValue(specificNfi).Equals(prop.GetValue(nfi))) + { + match = false; + break; + } + } + if (match) + { + Console.WriteLine("NumberFormatInfo object for '{0}' matches '{1}'", + name, ci.Name); + hasOneMatch = true; + } + } + if (!hasOneMatch) + Console.WriteLine("NumberFormatInfo object for '{0}' --> No Match", name); + + Console.WriteLine(); + } +} +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parse1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parse1.cs new file mode 100644 index 0000000000000..b4131e78d7fdb --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parse1.cs @@ -0,0 +1,41 @@ +// +using System; +using System.Globalization; + +public class ParseEx1 +{ + public static void Main() + { + String[] values = { "1,034,562.91", "9 532 978,07" }; + String[] cultureNames = { "en-US", "fr-FR", "" }; + + foreach (var value in values) + { + foreach (var cultureName in cultureNames) + { + CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName); + String name = culture.Name == "" ? "Invariant" : culture.Name; + try + { + Decimal amount = Decimal.Parse(value, culture); + Console.WriteLine("'{0}' --> {1} ({2})", value, amount, name); + } + catch (FormatException) + { + Console.WriteLine("'{0}': FormatException ({1})", + value, name); + } + } + Console.WriteLine(); + } + } +} +// The example displays the following output: +// '1,034,562.91' --> 1034562.91 (en-US) +// '1,034,562.91': FormatException (fr-FR) +// '1,034,562.91' --> 1034562.91 (Invariant) +// +// '9 532 978,07': FormatException (en-US) +// '9 532 978,07' --> 9532978.07 (fr-FR) +// '9 532 978,07': FormatException (Invariant) +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parsepersisted.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parsepersisted.cs new file mode 100644 index 0000000000000..23e05bd954e21 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parsepersisted.cs @@ -0,0 +1,80 @@ +// +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Threading; + +public class ParsePersistedEx +{ + public static void Main() + { + CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US"); + PersistData(); + + CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("pt-BR"); + RestoreData(); + } + + private static void PersistData() + { + // Define an array of floating-point values. + Double[] values = { 160325.972, 8631.16, 1.304e5, 98017554.385, + 8.5938287084321676e94 }; + Console.WriteLine("Original values: "); + foreach (var value in values) + Console.WriteLine(value.ToString("R", CultureInfo.InvariantCulture)); + + // Serialize an array of doubles to a file + StreamWriter sw = new StreamWriter(@".\NumericData.bin"); + for (int ctr = 0; ctr < values.Length; ctr++) + { + sw.Write(values[ctr].ToString("R")); + if (ctr < values.Length - 1) sw.Write("|"); + } + sw.Close(); + Console.WriteLine(); + } + + private static void RestoreData() + { + // Deserialize the data + StreamReader sr = new StreamReader(@".\NumericData.bin"); + String data = sr.ReadToEnd(); + sr.Close(); + + String[] stringValues = data.Split('|'); + List newValueList = new List(); + + foreach (var stringValue in stringValues) + { + try + { + newValueList.Add(Double.Parse(stringValue)); + } + catch (FormatException) + { + newValueList.Add(Double.NaN); + } + } + + Console.WriteLine("Restored values:"); + foreach (var newValue in newValueList) + Console.WriteLine(newValue.ToString("R", NumberFormatInfo.InvariantInfo)); + } +} +// The example displays the following output: +// Original values: +// 160325.972 +// 8631.16 +// 130400 +// 98017554.385 +// 8.5938287084321671E+94 +// +// Restored values: +// 160325972 +// 863116 +// 130400 +// 98017554385 +// 8.5938287084321666E+110 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parseuser1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parseuser1.cs new file mode 100644 index 0000000000000..0470738820851 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/parseuser1.cs @@ -0,0 +1,45 @@ +// +using System; +using System.Globalization; + +public class ParseUserEx +{ + public static void Main() + { + CultureInfo stdCulture = CultureInfo.GetCultureInfo("en-US"); + CultureInfo custCulture = CultureInfo.CreateSpecificCulture("en-US"); + + String value = "310,16"; + try + { + Console.WriteLine("{0} culture reflects user overrides: {1}", + stdCulture.Name, stdCulture.UseUserOverride); + Decimal amount = Decimal.Parse(value, stdCulture); + Console.WriteLine("'{0}' --> {1}", value, amount.ToString(CultureInfo.InvariantCulture)); + } + catch (FormatException) + { + Console.WriteLine("Unable to parse '{0}'", value); + } + Console.WriteLine(); + + try + { + Console.WriteLine("{0} culture reflects user overrides: {1}", + custCulture.Name, custCulture.UseUserOverride); + Decimal amount = Decimal.Parse(value, custCulture); + Console.WriteLine("'{0}' --> {1}", value, amount.ToString(CultureInfo.InvariantCulture)); + } + catch (FormatException) + { + Console.WriteLine("Unable to parse '{0}'", value); + } + } +} +// The example displays the following output: +// en-US culture reflects user overrides: False +// '310,16' --> 31016 +// +// en-US culture reflects user overrides: True +// '310,16' --> 310.16 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/project.csproj b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/project.csproj new file mode 100644 index 0000000000000..410c4a67f2207 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/project.csproj @@ -0,0 +1,9 @@ + + + + Library + net8.0 + enable + + + diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/properties1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/properties1.cs new file mode 100644 index 0000000000000..3be5c7e9cb886 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/properties1.cs @@ -0,0 +1,41 @@ +// +using System; +using System.Globalization; + +public class PropertiesEx1 +{ + public static void Main() + { + string[] formatStrings = { "C2", "E1", "F", "G3", "N", + "#,##0.000", "0,000,000,000.0##" }; + CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US"); + Decimal[] values = { 1345.6538m, 1921651.16m }; + + foreach (var value in values) + { + foreach (var formatString in formatStrings) + { + string resultString = value.ToString(formatString, culture); + Console.WriteLine("{0,-18} --> {1}", formatString, resultString); + } + Console.WriteLine(); + } + } +} +// The example displays the following output: +// C2 --> $1,345.65 +// E1 --> 1.3E+003 +// F --> 1345.65 +// G3 --> 1.35E+03 +// N --> 1,345.65 +// #,##0.000 --> 1,345.654 +// 0,000,000,000.0## --> 0,000,001,345.654 +// +// C2 --> $1,921,651.16 +// E1 --> 1.9E+006 +// F --> 1921651.16 +// G3 --> 1.92E+06 +// N --> 1,921,651.16 +// #,##0.000 --> 1,921,651.160 +// 0,000,000,000.0## --> 0,001,921,651.16 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/properties2.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/properties2.cs new file mode 100644 index 0000000000000..dee3c390c4ad0 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/NumberFormatInfo/csharp/properties2.cs @@ -0,0 +1,22 @@ +// +using System; + +public class PropertiesEx2 +{ + public static void Main() + { + Decimal[] values = { 1345.6538m, 1921651.16m }; + + foreach (var value in values) + { + string resultString = value.ToString(); + Console.WriteLine(resultString); + Console.WriteLine(); + } + } +} +// The example displays the following output: +// 1345.6538 +// +// 1921651.16 +// diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/RegionInfo/csharp/Project.csproj b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/RegionInfo/csharp/Project.csproj new file mode 100644 index 0000000000000..5a1b02db67729 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/RegionInfo/csharp/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net8.0 + + + \ No newline at end of file diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Globalization/RegionInfo/csharp/propertyvalues1.cs b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/RegionInfo/csharp/propertyvalues1.cs new file mode 100644 index 0000000000000..18ebcf53bbdae --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/System.Globalization/RegionInfo/csharp/propertyvalues1.cs @@ -0,0 +1,46 @@ +// +using System; +using System.Globalization; +using System.Reflection; + +public class Example +{ + public static void Main() + { + // Instantiate three Belgian RegionInfo objects. + RegionInfo BE = new RegionInfo("BE"); + RegionInfo frBE = new RegionInfo("fr-BE"); + RegionInfo nlBE = new RegionInfo("nl-BE"); + + RegionInfo[] regions = { BE, frBE, nlBE }; + PropertyInfo[] props = typeof(RegionInfo).GetProperties(BindingFlags.Instance | BindingFlags.Public); + + Console.WriteLine("{0,-30}{1,18}{2,18}{3,18}\n", + "RegionInfo Property", "BE", "fr-BE", "nl-BE"); + foreach (var prop in props) + { + Console.Write("{0,-30}", prop.Name); + foreach (var region in regions) + Console.Write("{0,18}", prop.GetValue(region, null)); + + Console.WriteLine(); + } + } +} +// The example displays the following output: +// RegionInfo Property BE fr-BE nl-BE +// +// Name BE fr-BE nl-BE +// EnglishName Belgium Belgium Belgium +// DisplayName Belgium Belgium Belgium +// NativeName België Belgique België +// TwoLetterISORegionName BE BE BE +// ThreeLetterISORegionName BEL BEL BEL +// ThreeLetterWindowsRegionName BEL BEL BEL +// IsMetric True True True +// GeoId 21 21 21 +// CurrencyEnglishName Euro Euro Euro +// CurrencyNativeName euro euro euro +// CurrencySymbol € € € +// ISOCurrencySymbol EUR EUR EUR +// diff --git a/docs/fundamentals/runtime-libraries/system-globalization-compareinfo.md b/docs/fundamentals/runtime-libraries/system-globalization-compareinfo.md new file mode 100644 index 0000000000000..ad66e6081f817 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-compareinfo.md @@ -0,0 +1,34 @@ +--- +title: System.Globalization.CompareInfo class +description: Learn more about the System.Globalization.CompareInfo class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +Conventions for comparing and sorting data vary from culture to culture. For example, sort order may be based on phonetics or on the visual representation of characters. In East Asian languages, characters are sorted by the stroke and radical of ideographs. Sorting also depends on the order languages and cultures use for the alphabet. For example, the Danish language has an "Æ" character that it sorts after "Z" in the alphabet. In addition, comparisons may be case-sensitive or case-insensitive, and casing rules may also differ by culture. The class is responsible for maintaining this culture-sensitive string comparison data and for performing culture-sensitive string operations. + +Typically, you do not have to instantiate a object directly, because one is used implicitly by all non-ordinal string comparison operations, including calls to the method. However, if you do want to retrieve a object, you can do it in one of these ways: + +- By retrieving the value of the property for a particular culture. + +- By calling the static method with a culture name. This allows for late-bound access to a object. + +## Ignored search values + +Character sets include ignorable characters, which are characters that are not considered when performing a linguistic or culture-sensitive comparison. Comparison methods such as and do not consider such characters when they perform a culture-sensitive comparison. Ignorable characters include: + +- . Culture-sensitive comparison methods will always find an empty string at the beginning (index zero) of the string being searched. + +- A character or string consisting of characters with code points that are not considered in the operation because of comparison options, In particular, the and options produce searches in which symbols and nonspacing combining characters are ignored. + +- A string with code points that have no linguistic significance. For example, a soft hyphen (U+00AD) is always ignored in a culture-sensitive string comparison. + +## Security considerations + +If a security decision depends on a string comparison or a case change, you should use the property to ensure that the behavior is consistent, regardless of the culture settings of the operating system. + +> [!NOTE] +> When possible, you should use string comparison methods that have a parameter of type to specify the kind of comparison expected. As a general rule, use linguistic options (using the current culture) for comparing strings displayed in the user interface and specify or for security comparisons. diff --git a/docs/fundamentals/runtime-libraries/system-globalization-compareoptions.md b/docs/fundamentals/runtime-libraries/system-globalization-compareoptions.md new file mode 100644 index 0000000000000..ca2b4e5e78e83 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-compareoptions.md @@ -0,0 +1,22 @@ +--- +title: System.Globalization.CompareOptions enum +description: Learn more about the System.Globalization.CompareOptions enum. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# enum + +[!INCLUDE [context](includes/context.md)] + +The options denote case sensitivity or necessity to ignore types of characters. + +.NET uses three distinct ways of sorting: word sort, string sort, and ordinal sort. Word sort performs a culture-sensitive comparison of strings. Certain nonalphanumeric characters might have special weights assigned to them. For example, the hyphen ("-") might have a very small weight assigned to it so that "coop" and "co-op" appear next to each other in a sorted list. String sort is similar to word sort, except that there are no special cases. Therefore, all nonalphanumeric symbols come before all alphanumeric characters. Ordinal sort compares strings based on the Unicode values of each element of the string. For a downloadable set of text files that contain information on the character weights used in sorting and comparison operations for Windows operating systems, see [Sorting Weight Tables](https://www.microsoft.com/download/details.aspx?id=10921). For the sort weight table for Linux and macOS, see the [Default Unicode Collation Element Table](https://www.unicode.org/Public/UCA/latest/allkeys.txt). The specific version of the sort weight table on Linux and macOS depends on the version of the [International Components for Unicode](https://icu.unicode.org/) libraries installed on the system. For information on ICU versions and the Unicode versions that they implement, see [Downloading ICU](https://icu.unicode.org/download). + +The `StringSort` value can only be used with and . is thrown if the StringSort value is used with , , , or . + +> [!NOTE] +> When possible, you should use string comparison methods that accept a value to specify the kind of comparison expected. As a general rule, user-facing comparisons are best served by the use of linguistic options (using the current culture), while security comparisons should specify `Ordinal` or `OrdinalIgnoreCase`. + +## Culture-sensitive sorts + +[!INCLUDE[platform-note](includes/c-and-posix-cultures.md)] diff --git a/docs/fundamentals/runtime-libraries/system-globalization-cultureandregioninfobuilder.md b/docs/fundamentals/runtime-libraries/system-globalization-cultureandregioninfobuilder.md new file mode 100644 index 0000000000000..3b8a932629df5 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-cultureandregioninfobuilder.md @@ -0,0 +1,63 @@ +--- +title: System.Globalization.CultureAndRegionInfoBuilder class +description: Learn more about the System.Globalization.CultureAndRegionInfoBuilder class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +The class holds culture-specific information, such as the associated language, sublanguage, country/region, calendar, and cultural conventions. This class also provides culture-specific instances of the , , , and classes, which are required for culture-specific operations such as casing, formatting and parsing dates and numbers, and comparing strings. + +By default, .NET supports objects that represent a predefined set of cultures. For a list of these cultures available on Windows systems, see the **Language tag** column in the [list of language/region names supported by Windows](/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c). Culture names follow the standard defined by [BCP 47](https://tools.ietf.org/html/bcp47). The class enables you to create a custom culture that is completely new or that overrides a predefined culture. When a custom culture is installed and registered on a particular computer, it becomes indistinguishable from predefined objects, and can be instantiated and used just like those objects. + +> [!IMPORTANT] +> Note that the class is found in an assembly named sysglobl.dll. Successfully compiling code that uses this type requires that you add a reference to sysglobl.dll. + +A custom culture can be registered on a computer only by a user who has administrative rights on that computer. Consequently, apps typically do not create and install custom cultures. Instead, you can use the class to create a special-purpose tool that an administrator can use to create, install, and register a custom culture. After the custom culture is registered on a computer, you can use the class in your app to create instances of the custom culture just as you would for a predefined culture. + +If you parse date and time strings generated for a custom culture, you should use the or method instead of the or method to improve the probability that the parse operation will succeed. A date and time string for a custom culture can be complicated and therefore difficult to parse. The and methods try to parse a string with several implicit parse patterns, all of which might fail. The method, in contrast, requires the application to explicitly designate one or more exact parse patterns that are likely to succeed. + +## Define and create a custom culture + +You use the class to define and name a custom culture. The custom culture can be an entirely new culture, a new culture that is based on an existing culture (that is, a supplemental culture), or a culture that replaces an existing .NET culture. In each case, the basic steps are the same: + +1. Instantiate a object by calling its constructor. To replace an existing culture, pass that culture's name and the enumeration value to the constructor. To create a new culture or a supplemental culture, pass a unique culture name and either the or enumeration value. + + > [!NOTE] + > If you use the enumeration value to instantiate a object, the object's properties are automatically populated with values from the object to be replaced. + +2. If you're creating a new or supplemental culture: + + - Populate the object's properties by calling the method and passing a object whose property values are similar to your new object. + - Populate the object's regional properties by calling the method and passing a object that represents the region of your custom culture. + +3. Modify the properties of the object as necessary. + +4. If you are planning to register the custom culture in a separate routine, call the method. This generates an XML file that you can load and register in a separate custom culture installation routine. + +## Register a custom culture + +If you are developing a registration application for a custom culture that is separate from the application that creates the culture, you call the method to load the XML file that contains the custom culture's definition and instantiate the object. To handle the registration, call the method. For the registration to succeed, the application that registers the custom culture must be running with administrative privileges on the target system; otherwise, the call to throws an exception. + +> [!WARNING] +> Culture data can differ between systems. If you're using the class to create a custom culture that is uniform across multiple systems and you are creating your custom culture by loading data from existing and objects and customizing it, you should develop two different utilities. The first creates the custom culture and saves it to an XML file. The second uses the method to load the custom culture from an XML file and register it on the target computer. + +The registration process performs the following tasks: + +- Creates an .nlp file that contains the information that is defined in the object. +- Stores the .nlp file in the %windir%\Globalization system directory on the target computer. This enables the custom culture's settings to persist between sessions. (The method requires administrative privileges because the .nlp file is stored in a system directory.) +- Prepares .NET to search the %windir%\Globalization system directory instead of an internal cache the next time there's a request to create your new custom culture. + +When a custom culture is successfully registered, it's indistinguishable from the cultures that are predefined by .NET. The custom culture is available until a call to the method removes the .nlp file from the local computer. + +## Instantiate a custom culture + +You can create an instance of the custom culture in one of the following ways: + +- By invoking the constructor with the culture name. +- By calling the method with the culture name. +- By calling the method with the culture name. + +In addition, the array of objects that is returned by the method includes the custom culture. diff --git a/docs/fundamentals/runtime-libraries/system-globalization-cultureinfo.md b/docs/fundamentals/runtime-libraries/system-globalization-cultureinfo.md new file mode 100644 index 0000000000000..5a54cc4a3e235 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-cultureinfo.md @@ -0,0 +1,232 @@ +--- +title: System.Globalization.CultureInfo class +description: Learn more about the System.Globalization.CultureInfo class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +The class provides culture-specific information, such as the language, sublanguage, country/region, calendar, and conventions associated with a particular culture. This class also provides access to culture-specific instances of the , , , and objects. These objects contain the information required for culture-specific operations, such as casing, formatting dates and numbers, and comparing strings. The class is used either directly or indirectly by classes that format, parse, or manipulate culture-specific data, such as , , , and the numeric types. + +## Culture names and identifiers + +The class specifies a unique name for each culture, based on RFC 4646. The name is a combination of an ISO 639 two-letter or three-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region. In addition, for apps that target .NET Framework 4 or later and are running under Windows 10 or later, culture names that correspond to valid BCP-47 language tags are supported. + +> [!NOTE] +> When a culture name is passed to a class constructor or a method such as or , its case is not significant. + +The format for the culture name based on RFC 4646 is *`languagecode2`*-*`country/regioncode2`*, where *`languagecode2`* is the two-letter language code and *`country/regioncode2`* is the two-letter subculture code. Examples include `ja-JP` for Japanese (Japan) and `en-US` for English (United States). In cases where a two-letter language code is not available, a three-letter code as defined in ISO 639-3 is used. + +Some culture names also specify an ISO 15924 script. For example, Cyrl specifies the Cyrillic script and Latn specifies the Latin script. A culture name that includes a script uses the pattern *`languagecode2`*-*`scripttag`*-*`country/regioncode2`*. An example of this type of culture name is `uz-Cyrl-UZ` for Uzbek (Cyrillic, Uzbekistan). On Windows operating systems before Windows Vista, a culture name that includes a script uses the pattern *`languagecode2`*-*`country/regioncode2`*-*`scripttag`*, for example, `uz-UZ-Cyrl` for Uzbek (Cyrillic, Uzbekistan). + +A neutral culture is specified by only the two-letter, lowercase language code. For example, `fr` specifies the neutral culture for French, and `de` specifies the neutral culture for German. + +> [!NOTE] +> There are two culture names that contradict this rule. The cultures Chinese (Simplified), named `zh-Hans`, and Chinese (Traditional), named `zh-Hant`, are neutral cultures. The culture names represent the current standard and should be used unless you have a reason for using the older names `zh-CHS` and `zh-CHT`. + +A culture identifier is a standard international numeric abbreviation and has the components necessary to uniquely identify one of the installed cultures. Your application can use predefined culture identifiers or define custom identifiers. + +Certain predefined culture names and identifiers are used by this and other classes in the namespace. For detailed culture information for Windows systems, see the **Language tag** column in the [list of language/region names supported by Windows](/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c). Culture names follow the standard defined by [BCP 47](https://tools.ietf.org/html/bcp47). + +The culture names and identifiers represent only a subset of cultures that can be found on a particular computer. Windows versions or service packs can change the available cultures. Applications can add custom cultures using the class. Users can add their own custom cultures using the [Microsoft Locale Builder](https://www.microsoft.com/download/details.aspx?id=41158) tool. Microsoft Locale Builder is written in managed code using the `CultureAndRegionInfoBuilder` class. + +Several distinct names are closely associated with a culture, notably the names associated with the following class members: + +- +- +- + +## Invariant, neutral, and specific cultures + +The cultures are generally grouped into three sets: invariant cultures, neutral cultures, and specific cultures. + +An invariant culture is culture-insensitive. Your application specifies the invariant culture by name using an empty string ("") or by its identifier. defines an instance of the invariant culture. It is associated with the English language but not with any country/region. It is used in almost any method in the `Globalization` namespace that requires a culture. + +A neutral culture is a culture that is associated with a language but not with a country/region. A specific culture is a culture that is associated with a language and a country/region. For example, `fr` is the neutral name for the French culture, and `fr-FR` is the name of the specific French (France) culture. Note that Chinese (Simplified) and Chinese (Traditional) are also considered neutral cultures. + +Creating an instance of a class for a neutral culture is not recommended because the data it contains is arbitrary. To display and sort data, specify both the language and region. Additionally, the property of a object created for a neutral culture returns only the country and does not include the region. + +The defined cultures have a hierarchy in which the parent of a specific culture is a neutral culture and the parent of a neutral culture is the invariant culture. The property contains the neutral culture associated with a specific culture. Custom cultures should define the property in conformance with this pattern. + +If the resources for a specific culture are not available in the operating system, the resources for the associated neutral culture are used. If the resources for the neutral culture are not available, the resources embedded in the main assembly are used. For more information on the resource fallback process, see [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps). + +The list of locales in the Windows API is slightly different from the list of cultures supported by .NET. If interoperability with Windows is required, for example, through the p/invoke mechanism, the application should use a specific culture that's defined for the operating system. Use of the specific culture ensures consistency with the equivalent Windows locale, which is identified with a locale identifier that is the same as . + +A or a can be created only for the invariant culture or for specific cultures, not for neutral cultures. + +If is the but the is not set to `zh-TW`, then , , and return an empty string (""). + +## Custom cultures + +On Windows, you can create custom locales. For more information, see [Custom locales](/windows/win32/intl/custom-locales). + +## CultureInfo and cultural data + +.NET derives its cultural data from a one of a variety of sources, depending on implementation, platform, and version: + +- In all versions of .NET (Core) running on Unix platforms or Windows 10 and later versions, cultural data is provided by the [International Components for Unicode (ICU) Library](https://icu.unicode.org/). The specific version of the ICU Library depends on the individual operating system. +- In all versions of .NET (Core) running on Windows 9 and earlier versions, cultural data is provided by the Windows operating system. +- In .NET Framework 4 and later versions, cultural data is provided by the Windows operating system. +- In .NET Framework 3.5 and earlier versions, cultural data is provided by both the Windows operating system and .NET Framework. + +Because of this, a culture available on a particular .NET implementation, platform, or version may not be available on a different .NET implementation, platform, or version. + +Some `CultureInfo` objects differ depending on the underlying platform. In particular, `zh-CN`, or Chinese (Simplified, China) and `zh-TW`, or Chinese (Traditional, Taiwan), are available cultures on Windows systems, but they are aliased cultures on Unix systems. "zh-CN" is an alias for the "zh-Hans-CN" culture, and "zh-TW" is an alias for the "zh-Hant-TW" culture. Aliased cultures are not returned by calls to the method and may have different property values, including different cultures, than their Windows counterparts. For the `zh-CN` and `zh-TW` cultures, these differenes include the following: + +- On Windows systems, the parent culture of the "zh-CN" culture is "zh-Hans", and the parent culture of the "zh-TW" culture is "zh-Hant". The parent culture of both these cultures is "zh". On Unix systems, the parents of both cultures are "zh". This means that, if you don't provide culture-specific resources for the "zh-CN" or "zh-TW" cultures but do provide a resources for the neutral "zh-Hans" or "zh-Hant" culture, your application will load the resources for the neutral culture on Windows but not on Unix. On Unix systems, you must explicitly set the thread's to either "zh-Hans" or "zh-Hant". + +- On Windows systems, calling on an instance that represents the "zh-CN" culture and passing it a "zh-Hans-CN" instance returns `true`. On Unix systems, the method call returns `false`. This behavior also applies to calling on a "zh-TW" instance and passing it a "zh-Hant-Tw" instance. + +## Dynamic culture data + +Except for the invariant culture, culture data is dynamic. This is true even for the predefined cultures. For example, countries or regions adopt new currencies, change their spellings of words, or change their preferred calendar, and culture definitions change to track this. Custom cultures are subject to change without notice, and any specific culture might be overridden by a custom replacement culture. Also, as discussed below, an individual user can override cultural preferences. Applications should always obtain culture data at run time. + +> [!CAUTION] +> When saving data, your application should use the invariant culture, a binary format, or a specific culture-independent format. Data saved according to the current values associated with a particular culture, other than the invariant culture, might become unreadable or might change in meaning if that culture changes. + +## The current culture and current UI culture + +Every thread in a .NET application has a current culture and a current UI culture. The current culture determines the formatting conventions for dates, times, numbers, and currency values, the sort order of text, casing conventions, and the ways in which strings are compared. The current UI culture is used to retrieve culture-specific resources at run time. + +> [!NOTE] +> For information on how the current and current UI culture is determined on a per-thread basis, see the [Culture and threads](#culture-and-threads) section. For information on how the current and current UI culture is determined on threads executing in a new application domain, and on threads that cross application domain boundaries, see the [Culture and application domains](#culture-and-application-domains) section. For information on how the current and current UI culture is determined on threads performing task-based asynchronous operations, see the [Culture and task-based asynchronous operations](#culture-and-task-based-asynchronous-operations) section. + +For more detailed information on the current culture, see the property. For more detailed information on the current UI culture, see the property topic. + +### Retrieve the current and current UI cultures + +You can get a object that represents the current culture in either of two ways: + +- By retrieving the value of the property. +- By retrieving the value of the [Thread.CurrentThread.CurrentCulture]() property. + +The following example retrieves both property values, compares them to show that they are equal, and displays the name of the current culture. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/Current1.cs" id="Snippet1"::: + +You can get a object that represents the current UI culture in either of two ways: + +- By retrieving the value of the property. + +- By retrieving the value of the [Thread.CurrentThread.CurrentUICulture]() property. + +The following example retrieves both property values, compares them to show that they are equal, and displays the name of the current UI culture. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/CurrentUI1.cs" id="Snippet2"::: + +### Set the current and current UI cultures + +To change the culture and UI culture of a thread, do the following: + +1. Instantiate a object that represents that culture by calling a class constructor and passing it the name of the culture. The constructor instantiates a object that reflects user overrides if the new culture is the same as the current Windows culture. The constructor allows you to specify whether the newly instantiated object reflects user overrides if the new culture is the same as the current Windows culture. + +2. Assign the object to the or property on .NET Core and .NET Framework 4.6 and later versions. (On .NET Framework 4.5.2 and earlier versions, you can assign the `CultureInfo` object to the or property.) + +The following example retrieves the current culture. If it is anything other than the French (France) culture, it changes the current culture to French (France). Otherwise, it changes the current culture to French (Luxembourg). + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/Change1.cs" id="Snippet3"::: + +The following example retrieves the current culture. If it is anything other the Slovenian (Slovenia) culture, it changes the current culture to Slovenian (Slovenia). Otherwise, it changes the current culture to Croatian (Croatia). + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/ChangeUI1.cs" id="Snippet4"::: + +## Get all cultures + +You can retrieve an array of specific categories of cultures or of all the cultures available on the local computer by calling the method. For example, you can retrieve custom cultures, specific cultures, or neutral cultures either alone or in combination. + +The following example calls the method twice, first with the enumeration member to retrieve all custom cultures, and then with the enumeration member to retrieve all replacement cultures. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/GetCultures1.cs" id="Snippet5"::: + +## Culture and threads + +When a new application thread is started, its current culture and current UI culture are defined by the current system culture, and not by the current thread culture. The following example illustrates the difference. It sets the current culture and current UI culture of an application thread to the French (France) culture (fr-FR). If the current culture is already fr-FR, the example sets it to the English (United States) culture (en-US). It displays three random numbers as currency values and then creates a new thread, which, in turn, displays three more random numbers as currency values. But as the output from the example shows, the currency values displayed by the new thread do not reflect the formatting conventions of the French (France) culture, unlike the output from the main application thread. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/defaultthread1.cs" id="Snippet1"::: + +You can set the culture and UI culture of all threads in an application domain by assigning a object that represents that culture to the and properties. The following example uses these properties to ensure that all threads in the default application domain share the same culture. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/setthreads1.cs" id="Snippet3"::: + +> [!WARNING] +> Although the and properties are static members, they define the default culture and default UI culture only for the application domain that is current at the time these property values are set. For more information, see the next section, [Culture and application domains](#culture-and-application-domains). + +When you assign values to the and properties, the culture and UI culture of the threads in the application domain also change if they have not explicitly been assigned a culture. However, these threads reflect the new culture settings only while they execute in the current application domain. If these threads execute in another application domain, their culture becomes the default culture defined for that application domain. As a result, we recommend that you always set the culture of the main application thread, and not rely on the and properties to change it. + +## Culture and application domains + + and are static properties that explicitly define a default culture only for the application domain that is current when the property value is set or retrieved. The following example sets the default culture and default UI culture in the default application domain to French (France), and then uses the class and the delegate to set the default culture and UI culture in a new application domain to Russian (Russia). A single thread then executes two methods in each application domain. Note that the thread's culture and UI culture are not explicitly set; they are derived from the default culture and UI culture of the application domain in which the thread is executing. Note also that the and properties return the default values of the application domain that is current when the method call is made. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/appdomainex1.cs" id="Snippet1"::: + +For more information about cultures and application domains, see the "Application Domains and Threads" section in the [Application Domains](../../framework/app-domains/application-domains.md) topic. + +## Culture and task-based asynchronous operations + +The [task-based asynchronous programming pattern](../../standard/parallel-programming/task-based-asynchronous-programming.md) uses and objects to asynchronously execute delegates on thread pool threads. The specific thread on which a particular task runs is not known in advance, but is determined only at runtime. + +For apps that target .NET Framework 4.6 or a later version, culture is part of an asynchronous operation's context. In other words, asynchronous operations by default inherit the values of the and properties of the thread from which they are launched. If the current culture or current UI culture differs from the system culture, the current culture crosses thread boundaries and becomes the current culture of the thread pool thread that is executing an asynchronous operation. + +The following example provides a simple illustration. The example defines a delegate, `formatDelegate`, that returns some numbers formatted as currency values. The example changes the current system culture to either French (France) or, if French (France) is already the current culture, English (United States). It then: + +- Invokes the delegate directly so that it runs synchronously on the main app thread. +- Creates a task that executes the delegate asynchronously on a thread pool thread. +- Creates a task that executes the delegate synchronously on the main app thread by calling the method. + +As the output from the example shows, when the current culture is changed to French (France), the current culture of the thread from which tasks are invoked asynchronously becomes the current culture for that asynchronous operation. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/asyncculture1.cs" id="Snippet1"::: + +For apps that target versions of .NET Framework from .NET Framework 4.5 and later but prior to .NET Framework 4.6, you can use the and properties to ensure that the culture of the calling thread is used in asynchronous tasks that execute on thread pool threads. The following example is identical to the previous example, except that it uses the property to ensure that thread pool threads have the same culture as the main app thread. + +:::code language="csharp" source="./snippets/System.Globalization/CultureInfo/csharp/asyncculture3.cs" id="Snippet3"::: + + and are per-app domain properties; that is, they establish a default culture for all threads not explicitly assigned a culture in a specific application domain. However, for apps that target .NET Framework 4.6 or later, the culture of the calling thread remains part of an asynchronous task's context even if the task crosses app domain boundaries. + +## CultureInfo object serialization + +When a object is serialized, all that is actually stored is and . It is successfully deserialized only in an environment where that has the same meaning. The following three examples show why this is not always the case: + +- If the property value is , and if that culture was first introduced in a particular version of the Windows operating system, it is not possible to deserialize it on an earlier version of Windows. For example, if a culture was introduced in Windows 10, it cannot be deserialized on Windows 8. + +- If the value is , and the computer on which it is deserialized does not have this user custom culture installed, it is not possible to deserialize it. + +- If the value is , and the computer on which it is deserialized does not have this replacement culture, it deserializes to the same name, but not all of the same characteristics. For example, if `en-US` is a replacement culture on computer A, but not on computer B, and if a object referring to this culture is serialized on computer A and deserialized on computer B, then none of the custom characteristics of the culture are transmitted. The culture deserializes successfully, but with a different meaning. + +## Control Panel overrides + +The user might choose to override some of the values associated with the current culture of Windows through the regional and language options portion of Control Panel. For example, the user might choose to display the date in a different format or to use a currency other than the default for the culture. In general, your applications should honor these user overrides. + +If is `true` and the specified culture matches the current culture of Windows, the uses those overrides, including user settings for the properties of the instance returned by the property, and the properties of the instance returned by the property. If the user settings are incompatible with the culture associated with the , for example, if the selected calendar is not one of the , the results of the methods and the values of the properties are undefined. + +## Alternate sort orders + +Some cultures support more than one sort order. For example: + +- The Spanish (Spain) culture has two sort orders: the default international sort order, and the traditional sort order. When you instantiate a object with the `es-ES` culture name, the international sort order is used. When you instantiate a object with the `es-ES-tradnl` culture name, the traditional sort order is used. + +- The `zh-CN` (Chinese (Simplified, PRC)) culture supports two sort orders: by pronunciation (the default) and by stroke count. When you instantiate a object with the `zh-CN` culture name, the default sort order is used. When you instantiate a object with a local identifier of 0x00020804, strings are sorted by stroke count. + +The following table lists the cultures that support alternate sort orders and the identifiers for the default and alternate sort orders. + +|Culture name|Culture|Default sort name and identifier|Alternate sort name and identifier| +|------------------|-------------|--------------------------------------|----------------------------------------| +|es-ES|Spanish (Spain)|International: 0x00000C0A|Traditional: 0x0000040A| +|zh-TW|Chinese (Taiwan)|Stroke Count: 0x00000404|Bopomofo: 0x00030404| +|zh-CN|Chinese (PRC)|Pronunciation: 0x00000804|Stroke Count: 0x00020804| +|zh-HK|Chinese (Hong Kong SAR)|Stroke Count: 0x00000c04|Stroke Count: 0x00020c04| +|zh-SG|Chinese (Singapore)|Pronunciation: 0x00001004|Stroke Count: 0x00021004| +|zh-MO|Chinese (Macao SAR)|Pronunciation: 0x00001404|Stroke Count: 0x00021404| +|ja-JP|Japanese (Japan)|Default: 0x00000411|Unicode: 0x00010411| +|ko-KR|Korean (Korea)|Default: 0x00000412|Korean Xwansung - Unicode: 0x00010412| +|de-DE|German (Germany)|Dictionary: 0x00000407|Phone Book Sort DIN: 0x00010407| +|hu-HU|Hungarian (Hungary)|Default: 0x0000040e|Technical Sort: 0x0001040e| +|ka-GE|Georgian (Georgia)|Traditional: 0x00000437|Modern Sort: 0x00010437| + +## The current culture and UWP apps + +In Universal Windows Platform (UWP) apps, the and properties are read-write, just as they are in .NET Framework and .NET Core apps. However, UWP apps recognize a single culture. The and properties map to the first value in the [Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages](/uwp/api/windows.applicationmodel.resources.core.resourcecontext#properties_) collection. + +In .NET apps, the current culture is a per-thread setting, and the and properties reflect the culture and UI culture of the current thread only. In UWP apps, the current culture maps to the [Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages](/uwp/api/windows.applicationmodel.resources.core.resourcecontext#properties_) collection, which is a global setting. Setting the or property changes the culture of the entire app; culture cannot be set on a per-thread basis. diff --git a/docs/fundamentals/runtime-libraries/system-globalization-datetimeformatinfo.md b/docs/fundamentals/runtime-libraries/system-globalization-datetimeformatinfo.md new file mode 100644 index 0000000000000..67c8066c365c7 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-datetimeformatinfo.md @@ -0,0 +1,282 @@ +--- +title: System.Globalization.DateTimeFormatInfo class +description: Learn more about the System.Globalization.DateTimeFormatInfo class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +The properties of the class contain culture-specific information for formatting or parsing date and time values such as the following: + +- The patterns used to format date values. +- The patterns used to format time values. +- The names of the days of the week. +- The names of the months of the year. +- The A.M. and P.M. designators used in time values. +- The calendar in which dates are expressed. + +## Instantiate a DateTimeFormatInfo object + +A object can represent the formatting conventions of the invariant culture, a specific culture, a neutral culture, or the current culture. This section discusses how to instantiate each type of object. + +### Instantiate a DateTimeFormatInfo object for the invariant culture + +The invariant culture represents a culture that is culture-insensitive. It is based on the English language, but not on any specific English-speaking country/region. Although the data of specific cultures can be dynamic and can change to reflect new cultural conventions or user preferences, the data of the invariant culture does not change. You can instantiate a object that represents the formatting conventions of the invariant culture in the following ways: + +- By retrieving the value of the property. The returned object is read-only. +- By calling the parameterless constructor. The returned object is read/write. +- By retrieving the value of the property from the object that is returned by the property. The returned object is read-only. + +The following example uses each of these methods to instantiate a object that represents the invariant culture. It then indicates whether the object is read-only. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/create1.cs" interactive="try-dotnet-method" id="Snippet1"::: + +### Instantiate a DateTimeFormatInfo object for a specific culture + +A specific culture represents a language that is spoken in a particular country/region. For example, en-US is a specific culture that represents the English language spoken in the United States, and en-CA is a specific culture that represents the English language spoken in Canada. You can instantiate a object that represents the formatting conventions of a specific culture in the following ways: + +- By calling the method and retrieving the value of the returned object's property. The returned object is read-only. + +- By passing the static method a object that represents the culture whose object you want to retrieve. The returned object is read/write. + +- By calling the static method and retrieving the value of the returned object's property. The returned object is read/write. + +- By calling the class constructor and retrieving the value of the returned object's property. The returned object is read/write. + +The following example illustrates each of these ways to instantiate a object and indicates whether the resulting object is read-only. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/create1.cs" interactive="try-dotnet-method" id="Snippet3"::: + +### Instantiate a DateTimeFormatInfo object for a neutral culture + +A neutral culture represents a culture or language that is independent of a country/region; it is typically the parent of one or more specific cultures. For example, Fr is a neutral culture for the French language and the parent of the fr-FR culture. You can instantiate a object that represents the formatting conventions of a neutral culture in the same ways that you create a object that represents the formatting conventions of a specific culture. In addition, you can retrieve a neutral culture's object by retrieving a neutral culture from a specific culture's property and retrieving the object returned by its property. Unless the parent culture represents the invariant culture, the returned object is read/write. The following example illustrates these ways of instantiating a object that represents a neutral culture. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/create1.cs" interactive="try-dotnet-method" id="Snippet2"::: + +However, a neutral culture lacks culture-specific formatting information, because it is independent of a specific country/region. Instead of populating the object with generic values, .NET returns a object that reflects the formatting conventions of a specific culture that is a child of the neutral culture. For example, the object for the neutral en culture reflects the formatting conventions of the en-US culture, and the object for the fr culture reflects the formatting conventions of the fr-FR culture. + +You can use code like the following to determine which specific culture's formatting conventions a neutral culture represents. The example uses reflection to compare the properties of a neutral culture with the properties of a specific child culture. It considers two calendars to be equivalent if they are the same calendar type and, for Gregorian calendars, if their properties have identical values. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate6.cs" interactive="try-dotnet" id="Snippet6"::: + +### Instantiate a DateTimeFormatInfo object for the current culture + +You can instantiate a object that represents the formatting conventions of the current culture in the following ways: + +- By retrieving the value of the property. The returned object is read-only. + +- By retrieving the value of the property from the object that is returned by the property. The returned object is read-only. + +- By calling the method with a object that represents the current culture. The returned object is read-only. + +The following example uses each of these methods to instantiate a object that represents the formatting conventions of the current culture. It then indicates whether the object is read-only. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/create2.cs" interactive="try-dotnet-method" id="Snippet4"::: + +You can create a writable object that represents the conventions of the current culture in one of these ways: + +- By retrieving a object in any of the three previous ways and calling the method on the returned object. This creates a copy of the original object, except that its property is `false`. + +- By calling the method to create a object that represents the current culture, and then using its property to retrieve the object. + +The following example illustrates each way of instantiating a read/write object and displays the value of its property. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate2.cs" id="Snippet7"::: + +In Windows, the user can override some of the property values used in formatting and parsing operations through the **Region and Language** application in Control Panel. For example, a user whose culture is English (United States) might choose to display long time values using a 24-hour clock (in the format HH:mm:ss) instead of the default 12-hour clock (in the format h:mm:ss tt). The objects retrieved in the ways discussed previously all reflect these user overrides. If this is undesirable, you can create a object that does not reflect user overrides (and is also read/write instead of read-only) by calling the constructor and supplying a value of `false` for the `useUserOverride` argument. The following example illustrates this for a system whose current culture is English (United States) and whose long time pattern has been changed from the default of h:mm:ss tt to HH:mm:ss. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/instantiate3.cs" id="Snippet8"::: + +## DateTimeFormatInfo and dynamic data + +The culture-specific data for formatting date and time values provided by the class is dynamic, just like cultural data provided by the class. You should not make any assumptions about the stability of values for objects that are associated with particular objects. Only the data provided by the invariant culture and its associated object is stable. Other data can change between application sessions or even while your application is running. There are four major sources of change: + +- System updates. Cultural preferences such as the preferred calendar or customary date and time formats change over time. When this happens, Windows Update includes changes to the property value for a particular culture. + +- Replacement cultures. The class can be used to replace the data of an existing culture. + +- Cascading changes to property values. A number of culture-related properties can change at run time, which, in turn, causes data to change. For example, the current culture can be changed either programmatically or through user action. When this happens, the object returned by the property changes to an object associated with the current culture. Similarly, a culture's calendar can change, which can result in changes to numerous property values. + +- User preferences. Users of your application might choose to override some of the values associated with the current system culture through the regional and language options in Control Panel. For example, users might choose to display the date in a different format. If the property is set to `true`, the properties of the object is also retrieved from the user settings. If the user settings are incompatible with the culture associated with the object (for example, if the selected calendar is not one of the calendars indicated by the property), the results of the methods and the values of the properties are undefined. + +To minimize the possibility of inconsistent data, all user-overridable properties of a object are initialized when the object is created. There is still a possibility of inconsistency, because neither object creation nor the user override process is atomic and the relevant values can change during object creation. However, this situation should be extremely rare. + +You can control whether user overrides are reflected in objects that represent the same culture as the system culture. The following table lists the ways in which a object can be retrieved and indicates whether the resulting object reflects user overrides. + +|Source of CultureInfo and DateTimeFormatInfo object|Reflects user overrides| +|---------------------------------------------------------|-----------------------------| +|`CultureInfo.CurrentCulture.DateTimeFormat` property|Yes| +| property|Yes| +| method|Yes| +| method|No| +| constructor|Yes| +| constructor|Depends on value of `useUserOverride` parameter| + +Unless there is a compelling reason to do otherwise, you should respect user overrides when you use the object in client applications to format and parse user input or to display data. For server applications or unattended applications, you should not. However, if you are using the object either explicitly or implicitly to persist date and time data in string form, you should either use a object that reflects the formatting conventions of the invariant culture, or you should specify a custom date and time format string that you use regardless of culture. + +## Format dates and times + +A object is used implicitly or explicitly in all date and time formatting operations. These include calls to the following methods: + +- All date and time formatting methods, such as and . +- The major composite formatting method, which is . +- Other composite formatting methods, such as and . + +All date and time formatting operations make use of an implementation. The interface includes a single method, . This callback method is passed a object that represents the type needed to provide formatting information. The method returns either an instance of that type or `null` if it cannot provide an instance of the type. .NET includes two implementations for formatting dates and times: + +- The class, which represents a specific culture (or a specific language in a specific country/region). In a date and time formatting operation, the method returns the object associated with its property. +- The class, which provides information about the formatting conventions of its associated culture. The method returns an instance of itself. + +If an implementation is not provided to a formatting method explicitly, the object returned by the property that represents the current culture is used. + +The following example illustrates the relationship between the interface and the class in formatting operations. It defines a custom implementation whose method displays the type of the object requested by the formatting operation. If it is requesting a object, the method provides the object for the current culture. As the output from the example shows, the method requests a object to provide formatting information, whereas the method requests and objects as well as an implementation. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/formatprovider1.cs" id="Snippet9"::: + +## Format strings and DateTimeFormatInfo properties + +The object includes three kinds of properties that are used in formatting operations with date and time values: + +- Calendar-related properties. Properties such as , , , and , are associated with the calendar used by the culture, which is defined by the property. These properties are used for long date and time formats. + +- Properties that produce a standards-defined result string. The , , and properties contain custom format strings that produce result strings defined by international standards. These properties are read-only and cannot be modified. + +- Properties that define culture-sensitive result strings. Some properties, such as and , contain [custom format strings](../../standard/base-types/custom-date-and-time-format-strings.md) that specify the format of the result string. Others, such as , , , and , define culture-sensitive symbols or substrings that can be included in a result string. + +The [standard date and time format strings](../../standard/base-types/standard-date-and-time-format-strings.md), such as "d", "D", "f", and "F", are aliases that correspond to particular format pattern properties. Most of the [custom date and time format strings](../../standard/base-types/custom-date-and-time-format-strings.md) are related to strings or substrings that a formatting operation inserts into the result stream. The following table lists the standard and custom date and time format specifiers and their associated properties. For details about how to use these format specifiers, see [Standard Date and Time Format Strings](../../standard/base-types/standard-date-and-time-format-strings.md) and [Custom Date and Time Format Strings](../../standard/base-types/custom-date-and-time-format-strings.md). Note that each standard format string corresponds to a property whose value is a custom date and time format string. The individual specifiers in this custom format string in turn correspond to other properties. The table lists only the properties for which the standard format strings are aliases, and does not list properties that may be accessed by custom format strings assigned to those aliased properties. In addition, the table lists only custom format specifiers that correspond to properties. + +|Format specifier|Associated properties| +|----------------------|---------------------------| +|"d" (short date; standard format string)|, to define the overall format of the result string.| +|"D" (long date; standard format string)|, to define the overall format of the result string.| +|"f" (full date / short time; standard format string)|, to define the format of the date component of the result string.

, to define the format of the time component of the result string.| +|"F" (full date / long time; standard format string)|, to define the format of the date component of the result string.

, to define the format of the time component of the result string.| +|"g" (general date / short time; standard format string)|, to define the format of the date component of the result string.

, to define the format of the time component of the result string.| +|"G" (general date / long time; standard format string)|, to define the format of the date component of the result string.

, to define the format of the time component of the result string.| +|"M", "m" (month/day; standard format string)|, to define the overall format of the result string.| +|"O", "o" (round-trip date/time; standard format string)|None.| +|"R", "r" (RFC1123; standard format string)|, to define a result string that conforms to the RFC 1123 standard. The property is read-only.| +|"s" (sortable date/time; standard format string)|, to define a result string that conforms to the ISO 8601 standard. The property is read-only.| +|"t" (short time; standard format string)|, to define the overall format of the result string.| +|"T" (long time; standard format string)|, to define the overall format of the result string.| +|"u" (universal sortable date/time; standard format string)|, to define a result string that conforms to the ISO 8601 standard for coordinated universal time. The property is read-only.| +|"U" (universal full date/time; standard format string)|, to define the overall format of the result string.| +|"Y", "y" (year month; standard format string)|, to define the overall format of the result string.| +|"ddd" (custom format specifier)|, to include the abbreviated name of the day of the week in the result string.| +|"g", "gg" (custom format specifier)|Calls the method to insert the era name in the result string.| +|"MMM" (custom format specifier)|, to include the abbreviated month name in the result string.| +|"MMMM" (custom format specifier)| or , to include the full month name in the result string.| +|"t" (custom format specifier)| or , to include the first character of the AM/PM designator in the result string.| +|"tt" (custom format specifier)| or , to include the full AM/PM designator in the result string.| +|":" (custom format specifier)|, to include the time separator in the result string.| +|"/" (custom format specifier)|, to include the date separator in the result string.| + +## Modify DateTimeFormatInfo properties + +You can change the result string produced by date and time format strings by modifying the associated properties of a writable object. To determine if a object is writable, use the property. To customize a object in this way: + +1. Create a read/write copy of a object whose formatting conventions you want to modify. + +2. Modify the property or properties that are used to produce the desired result string. (For information about how formatting methods use properties to define result strings, see the previous section, [Format strings and DateTimeFormatInfo properties](#format-strings-and-datetimeformatinfo-properties).) + +3. Use the custom object you created as the argument in calls to formatting methods. + +There are two other ways to change the format of a result string: + +- You can use the class to define either a custom culture (a culture that has a unique name and that supplements existing cultures) or a replacement culture (one that is used instead of a specific culture). You can save and access this culture programmatically as you would any object supported by .NET. + +- If the result string is not culture-sensitive and doesn't follow a predefined format, you can use a custom date and time format string. For example, if you are serializing date and time data in the format YYYYMMDDHHmmss, you can generate the result string by passing the custom format string to the method, and you can convert the result string back to a value by calling the method. + +### Change the short date pattern + +The following example changes the format of a result string produced by the "d" (short date) standard format string. It changes the associated property for the en-US or English (United States) culture from its default of "M/d/yyyy" to "yyyy'-"MM"-"dd" and uses the "d" standard format string to display the date both before and after the property is changed. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/example1.cs" interactive="try-dotnet" id="Snippet10"::: + +### Change the date separator character + +The following example changes the date separator character in a object that represents the formatting conventions of the fr-FR culture. The example uses the "g" standard format string to display the date both before and after the property is changed. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/example3.cs" interactive="try-dotnet" id="Snippet12"::: + +### Change day name abbreviations and the long date pattern + +In some cases, the long date pattern, which typically displays the full day and month name along with the number of the day of the month and the year, may be too long. The following example shortens the long date pattern for the en-US culture to return a one-character or two-character day name abbreviation followed by the day number, the month name abbreviation, and the year. It does this by assigning shorter day name abbreviations to the array, and by modifying the custom format string assigned to the property. This affects the result strings returned by the "D" and "f" standard format strings. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/example2.cs" interactive="try-dotnet" id="Snippet13"::: + +Ordinarily, the change to the property also affects the property, which in turn defines the result string returned by the "F" standard format string. To preserve the original full date and time pattern, the example reassigns the original custom format string assigned to the property after the property is modified. + +### Change from a 12-hour clock to a 24-hour clock + +For many cultures in .NET, the time is expressed by using a 12-hour clock and an AM/PM designator. The following example defines a `ReplaceWith24HourClock` method that replaces any time format that uses a 12-hour clock with a format that uses a 24-hour clock. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/example5.cs" interactive="try-dotnet" id="Snippet14"::: + +The example uses a regular expression to modify the format string. The regular expression pattern `@"^(?\s*t+\s*)? (?(openAMPM) h+(?[^ht]+)$ | \s*h+(?[^ht]+)\s*t+)` is defined as follows: + +|Pattern|Description| +|-------------|-----------------| +|`^`|Begin the match at the beginning of the string.| +|`(?\s*t+\s*)?`|Match zero or one occurrence of zero or more white-space characters, followed by the letter "t" one or more times, followed by zero or more white-space characters. This capturing group is named `openAMPM`.| +|`(?(openAMPM) h+(?[^ht]+)$`|If the `openAMPM` group has a match, match the letter "h" one or more times, followed by one or more characters that are neither "h" nor "t". The match ends at the end of the string. All characters captured after "h" are included in a capturing group named `nonHours`.| +|`| \s*h+(?[^ht]+)\s*t+)`|If the `openAMPM` group does not have a match, match the letter "h" one or more times, followed by one or more characters that are neither "h" nor "t", followed by zero or more white-space characters. Finally, match one or more occurrences of the letter "t". All characters captured after "h" and before the white-spaces and "t" are included in a capturing group named `nonHours`.| + +The `nonHours` capturing group contains the minute and possibly the second component of a custom date and time format string, along with any time separator symbols. The replacement pattern `HH${nonHours}` prepends the substring "HH" to these elements. + +### Display and change the era in a date + +The following example adds the "g" custom format specifier to the property of an object that represents the formatting conventions of the en-US culture. This addition affects the following three standard format strings: + +- The "D" (long date) standard format string, which maps directly to the property. + +- The "f" (full date / short time) standard format string, which produces a result string that concatenates the substrings produced by the and properties. + +- The "F" (full date / long time) standard format string, which maps directly to the property. Because we have not explicitly set this property value, it is generated dynamically by concatenating the and properties. + +The example also shows how to change the era name for a culture whose calendar has a single era. In this case, the en-US culture uses the Gregorian calendar, which is represented by a object. The class supports a single era, which it names A.D. (Anno Domini). The example changes the era name to C.E. (Common Era) by replacing the "g" custom format specifier in the format string assigned to the property with a literal string. The use of a literal string is necessary, because the era name is typically returned by the method from private data in the culture tables supplied by either .NET or the operating system. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/example4.cs" interactive="try-dotnet" id="Snippet11"::: + +## Parse date and time strings + +Parsing involves converting the string representation of a date and time to a or value. Both of these types include the `Parse`, `TryParse`, `ParseExact`, and `TryParseExact` methods to support parsing operations. The `Parse` and `TryParse` methods convert a string that can have a variety of formats, whereas `ParseExact` and `TryParseExact` require that the string have a defined format or formats. If the parsing operation fails, `Parse` and `ParseExact` throw an exception, whereas `TryParse` and `TryParseExact` return `false`. + +The parsing methods implicitly or explicitly use a enumeration value to determine which style elements (such as leading, trailing, or inner white space) can be present in the string to be parsed, and how to interpret the parsed string or any missing elements. If you don't provide a value when you call the `Parse` or `TryParse` method, the default is , which is a composite style that includes the , , and flags. For the `ParseExact` and `TryParseExact` methods, the default is ; the input string must correspond precisely to a particular custom date and time format string. + +The parsing methods also implicitly or explicitly use a object that defines the specific symbols and patterns that can occur in the string to be parsed. If you don't provide a object, the object for the current culture is used by default. For more information about parsing date and time strings, see the individual parsing methods, such as , , , and . + +The following example illustrates the culture-sensitive nature of parsing date and time strings. It tries to parse two date strings by using the conventions of the en-US, en-GB, fr-FR, and fi-FI cultures. The date that is interpreted as 8/18/2014 in the en-US culture throws a exception in the other three cultures because 18 is interpreted as the month number. 1/2/2015 is parsed as the second day of the first month in the en-US culture, but as the first day of the second month in the remaining cultures. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/parse1.cs" interactive="try-dotnet" id="Snippet15"::: + +Date and time strings are typically parsed for two reasons: + +- To convert user input into a date and time value. +- To round-trip a date and time value; that is, to deserialize a date and time value that was previously serialized as a string. + +The following sections discuss these two operations in greater detail. + +### Parse user strings + +When you parse date and time strings input by the user, you should always instantiate a object that reflects the user's cultural settings, including any customizations the user may have made. Otherwise, the date and time object may have incorrect values. For information about how to instantiate a object that reflects user cultural customizations, see the [DateTimeFormatInfo and dynamic data](#datetimeformatinfo-and-dynamic-data) section. + +The following example illustrates the difference between a parsing operation that reflects user cultural settings and one that does not. In this case, the default system culture is en-US, but the user has used Control Panel, **Region and Language** to change the short date pattern from its default of "M/d/yyyy" to "yy/MM/dd". When the user enters a string that reflects user settings, and the string is parsed by a object that also reflects user settings (overrides), the parsing operation returns a correct result. However, when the string is parsed by a object that reflects standard en-US cultural settings, the parsing method throws a exception because it interprets 14 as the number of the month, not the last two digits of the year. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/parse2.cs" id="Snippet16"::: + +### Serialize and deserialize date and time data + +Serialized date and time data are expected to round-trip; that is, all serialized and deserialized values should be identical. If a date and time value represents a single moment in time, the deserialized value should represent the same moment in time regardless of the culture or time zone of the system on which it was restored. To round-trip date and time data successfully, you must use the conventions of the invariant culture, which is returned by the property, to generate and parse the data. The formatting and parsing operations should never reflect the conventions of the default culture. If you use default cultural settings, the portability of the data is strictly limited; it can be successfully deserialized only on a thread whose cultural-specific settings are identical to those of the thread on which it was serialized. In some cases, this means that the data cannot even be successfully serialized and deserialized on the same system. + +If the time component of a date and time value is significant, it should also be converted to UTC and serialized by using the "o" or "r" [standard format string](../../standard/base-types/standard-date-and-time-format-strings.md). The time data can then be restored by calling a parsing method and passing it the appropriate format string along with the invariant culture as the `provider` argument. + +The following example illustrates the process of round-tripping a date and time value. It serializes a date and time on a system that observes U.S. Pacific time and whose current culture is en-US. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize1.cs" id="Snippet17"::: + +It deserializes the data on a system in the Brussels, Copenhagen, Madrid and Paris time zone and whose current culture is fr-FR. The restored date is nine hours later than the original date, which reflects the time zone adjustment from eight hours behind UTC to one hour ahead of UTC. Both the original date and the restored date represent the same moment in time. + +:::code language="csharp" source="./snippets/System.Globalization/DateTimeFormatInfo/csharp/serialize2.cs" id="Snippet18"::: diff --git a/docs/fundamentals/runtime-libraries/system-globalization-numberformatinfo.md b/docs/fundamentals/runtime-libraries/system-globalization-numberformatinfo.md new file mode 100644 index 0000000000000..d8811e2d43878 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-numberformatinfo.md @@ -0,0 +1,234 @@ +--- +title: System.Globalization.NumberFormatInfo class +description: Learn more about the System.Globalization.NumberFormatInfo class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +The class contains culture-specific information that is used when you format and parse numeric values. This information includes the currency symbol, the decimal symbol, the group separator symbol, and the symbols for positive and negative signs. + +## Instantiate a NumberFormatInfo object + +You can instantiate a object that represents the formatting conventions of the current culture, the invariant culture, a specific culture, or a neutral culture. + +### Instantiate a NumberFormatInfo object for the current culture + +You can instantiate a object for the current culture in any of the following ways. In each case, the returned object is read-only. + +- By retrieving a object that represents the current culture from the property, and retrieving the object from its property. + +- By retrieving the object returned by the `static` (`Shared` in Visual Basic) property. + +- By calling the method with a object that represents the current culture. + +The following example uses these three ways to create objects that represent the formatting conventions of the current culture. It also retrieves the value of the property to illustrate that each object is read-only. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/instantiate1.cs" interactive="try-dotnet" id="Snippet1"::: + +You can create a writable object that represents the conventions of the current culture in any of the following ways: + +- By retrieving a object in any of the ways illustrated in the previous code example, and calling the method on the returned object. This creates a copy of the original object, except that its property is `false`. + +- By calling the method to create a object that represents the current culture, and then using its property to retrieve the object. + +The following example illustrates these two ways of instantiating a object, and displays the value of its property to illustrate that the object is not read-only. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/instantiate2.cs" id="Snippet2"::: + +Note that the Windows operating system allows the user to override some of the property values used in numeric formatting and parsing operations through the **Region and Language** item in Control Panel. For example, a user whose culture is English (United States) might choose to display currency values as 1.1 USD instead of the default of $1.1. The objects retrieved in the ways discussed previously all reflect these user overrides. If this is undesirable, you can create a object that does not reflect user overrides (and that is also read/write rather than read-only) by calling the constructor and supplying a value of `false` for the `useUserOverride` argument. The following example provides an illustration for a system whose current culture is English (United States) and whose currency symbol has been changed from the default of $ to USD. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/instantiate3.cs" id="Snippet3"::: + +If the property is set to `true`, the properties , , and are also retrieved from the user settings. If the user settings are incompatible with the culture associated with the object (for example, if the selected calendar is not one of the calendars listed by the property), the results of the methods and the values of the properties are undefined. + +### Instantiate a NumberFormatInfo object for the invariant culture + +The invariant culture represents a culture that is culture-insensitive. It is based on the English language but not on any specific English-speaking country/region. Although the data of specific cultures can be dynamic and can change to reflect new cultural conventions or user preferences, the data of the invariant culture does not change. A object that represents the formatting conventions of the invariant culture can be used for formatting operations in which result strings should not vary by culture. + +You can instantiate a object that represents the formatting conventions of the invariant culture in the following ways: + +- By retrieving the value of the property. The returned object is read-only. + +- By retrieving the value of the property from the object that is returned by the property. The returned object is read-only. + +- By calling the parameterless class constructor. The returned object is read/write. + +The following example uses each of these methods to instantiate a object that represents the invariant culture. It then indicates whether the object is read-only, + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/instantiate4.cs" interactive="try-dotnet" id="Snippet4"::: + +### Instantiate a NumberFormatInfo object for a specific culture + +A specific culture represents a language that is spoken in a particular country/region. For example, en-US is a specific culture that represents the English language spoken in the United States, and en-CA is a specific culture that represents the English language spoken in Canada. You can instantiate a object that represents the formatting conventions of a specific culture in the following ways: + +- By calling the method and retrieving the value of the returned object's property. The returned object is read-only. + +- By passing a object that represents the culture whose object you want to retrieve to the static method. The returned object is read/write. + +- By calling the method and retrieving the value of the returned object's property. The returned object is read/write. + +- By calling one of the class constructors and retrieving the value of the returned object's property. The returned object is read/write. + +The following example uses these four ways to create a object that reflects the formatting conventions of the Indonesian (Indonesia) culture. It also indicates whether each object is read-only. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/instantiate5.cs" interactive="try-dotnet" id="Snippet5"::: + +### Instantiate a NumberFormatInfo object for a neutral culture + +A neutral culture represents a culture or language that is independent of a country/region. It is typically the parent of one or more specific cultures. For example, fr is a neutral culture for the French language and the parent of the fr-FR culture. You create a object that represents the formatting conventions of a neutral culture in the same way that you create a object that represents the formatting conventions of a specific culture. + +However, because it is independent of a specific country/region, a neutral culture lacks culture-specific formatting information. Rather than populating the object with generic values, .NET returns a object that reflects the formatting conventions of a specific culture that is a child of the neutral culture. For example, the object for the neutral en culture reflects the formatting conventions of the en-US culture, and the object for the fr culture reflects the formatting conventions of the fr-FR culture. + +You can use code like the following to determine which specific culture's formatting conventions each neutral culture represents. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/instantiate6.cs" id="Snippet6"::: + +## Dynamic data + +The culture-specific data for formatting numeric values provided by the class is dynamic, just like the cultural data provided by the class. You should not make any assumptions about the stability of values for objects that are associated with particular objects. Only the data provided by the invariant culture and its associated object is stable. Other data can change between application sessions, or even within a single session, for the following reasons: + +- **System updates.** Cultural preferences such as the currency symbol or currency formats change over time. When this happens, Windows Update includes changes to the property value for a particular culture. + +- **Replacement cultures.** The class can be used to replace the data of an existing culture. + +- **Cascading changes to property values.** A number of culture-related properties can change at run time, which, in turn, causes data to change. For example, the current culture can be changed either programmatically or through user action. When this happens, the object returned by the property changes to an object associated with the current culture. + +- **User preferences.** Users of your application might override some of the values associated with the current system culture through the region and language options in Control Panel. For example, users might choose a different currency symbol or a different decimal separator symbol. If the property is set to `true` (its default value), the properties of the object are also retrieved from the user settings. + +All user-overridable properties of a object are initialized when the object is created. There is still a possibility of inconsistency, because neither object creation nor the user override process is atomic, and the relevant values may change during object creation. However, these inconsistencies should be extremely rare. + +You can control whether user overrides are reflected in objects that represent the same culture as the current culture. The following table lists the ways in which a object can be retrieved and indicates whether the resulting object reflects user overrides. + +|Source of CultureInfo and NumberFormatInfo object|Reflects user overrides| +|-------------------------------------------------------|-----------------------------| +|`CultureInfo.CurrentCulture.NumberFormat` property|Yes| +| property|Yes| +| method|Yes| +| method|No| +| constructor|Yes| +| constructor|Depends on value of `useUserOverride` parameter| + +Unless there is a compelling reason to do otherwise, you should respect user overrides when you use the object in client applications to format and parse user input or to display numeric data. For server applications or unattended applications, you should not respect user overrides. However, if you are using the object either explicitly or implicitly to persist numeric data in string form, you should either use a object that reflects the formatting conventions of the invariant culture, or you should specify a custom numeric format string that you use regardless of culture. + +## IFormatProvider, NumberFormatInfo, and numeric formatting + +A object is used implicitly or explicitly in all numeric formatting operations. These include calls to the following methods: + +- All numeric formatting methods, such as , , and . + +- The major composite formatting method, . + +- Other composite formatting methods, such as and . + +All numeric formatting operations make use of an implementation. The interface includes a single method, . This is a callback method that is passed a object that represents the type needed to provide formatting information. The method is responsible for returning either an instance of that type or `null`, if it cannot provide an instance of the type. .NET provides two implementations for formatting numbers: + +- The class, which represents a specific culture (or a specific language in a specific country/region). In a numeric formatting operation, the method returns the object associated with its property. + +- The class, which provides information about the formatting conventions of its associated culture. The method returns an instance of itself. + +If an implementation is not provided to a formatting method explicitly, a object returned by the property that represents the current culture is used. + +The following example illustrates the relationship between the interface and the class in formatting operations by defining a custom implementation. Its method displays the type name of the object requested by the formatting operation. If the interface is requesting a object, this method provides the object for the current culture. As the output from the example shows, the method requests a object to provide formatting information, whereas the method requests and objects as well as an implementation. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/formatprovider1.cs" id="Snippet1"::: + +If an implementation is not explicitly provided in a numeric formatting method call, the method calls the `CultureInfo.CurrentCulture.GetFormat` method, which returns the object that corresponds to the current culture. + +## Format strings and NumberFormatInfo properties + +Every formatting operation uses either a standard or a custom numeric format string to produce a result string from a number. In some cases, the use of a format string to produce a result string is explicit, as in the following example. This code calls the method to convert a value to a number of different string representations by using the formatting conventions of the en-US culture. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/properties1.cs" interactive="try-dotnet" id="Snippet2"::: + +In other cases, the use of a format string is implicit. For example, in the following method calls to the default or parameterless method, the value of the instance is formatted by using the general ("G") format specifier and the conventions of the current culture, which in this case is the en-US culture. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/properties2.cs" interactive="try-dotnet" id="Snippet3"::: + +Each standard numeric format string uses one or more properties to determine the pattern or the symbols used in the result string. Similarly, each custom numeric format specifier except "0" and "#" insert symbols in the result string that are defined by properties. The following table lists the standard and custom numeric format specifiers and their associated properties. To change the appearance of the result string for a particular culture, see the [Modify NumberFormatInfo properties](#modify-numberformatinfo-properties) section. For details about the use of these format specifiers, see [Standard Numeric Format Strings](../../standard/base-types/standard-numeric-format-strings.md) and [Custom Numeric Format Strings](../../standard/base-types/custom-numeric-format-strings.md). + +|Format specifier|Associated properties| +|----------------------|---------------------------| +|"C" or "c" (currency format specifier)|, to define the default number of fractional digits.

, to define the decimal separator symbol.

, to define the group or thousands separator.

, to define the sizes of integral groups.

, to define the pattern of negative currency values.

, to define the pattern of positive currency values.

, to define the currency symbol.

, to define the negative sign symbol.| +|"D" or "d" (decimal format specifier)|, to define the negative sign symbol.| +|"E" or "e" (exponential or scientific format specifier)|, to define the negative sign symbol in the mantissa and exponent.

, to define the decimal separator symbol.

, to define the positive sign symbol in the exponent.| +|"F" or "f" (fixed-point format specifier)|, to define the negative sign symbol.

, to define the default number of fractional digits.

, to define the decimal separator symbol.| +|"G" or "g" (general format specifier)|, to define the negative sign symbol.

, to define the decimal separator symbol.

, to define the positive sign symbol for result strings in exponential format.| +|"N" or "n" (number format specifier)|, to define the negative sign symbol.

, to define the default number of fractional digits.

, to define the decimal separator symbol.

, to define the group separator (thousands) symbol.

, to define the number of integral digits in a group.

, to define the format of negative values.| +|"P" or "p" (percent format specifier)|, to define the negative sign symbol.

, to define the default number of fractional digits.

, to define the decimal separator symbol.

, to define the group separator symbol.

, to define the number of integral digits in a group.

, to define the placement of the percent symbol and the negative symbol for negative values.

, to define the placement of the percent symbol for positive values.

, to define the percent symbol.| +|"R" or "r" (round-trip format specifier)|, to define the negative sign symbol.

, to define the decimal separator symbol.

, to define the positive sign symbol in an exponent.| +|"X" or "x" (hexadecimal format specifier)|None.| +|"." (decimal point custom format specifier)|, to define the decimal separator symbol.| +|"," (group separator custom format specifier)|, to define the group (thousands) separator symbol.| +|"%" (percentage placeholder custom format specifier)|, to define the percent symbol.| +|"‰" (per mille placeholder custom format specifier)|, to define the per mille symbol.| +|"E" (exponential notation custom format specifier)|, to define the negative sign symbol in the mantissa and exponent.

, to define the positive sign symbol in the exponent.| + +Note that the class includes a property that specifies the base 10 digits used by a specific culture. However, the property is not used in formatting operations; only the Basic Latin digits 0 (U+0030) through 9 (U+0039) are used in the result string. In addition, for and values of `NaN`, `PositiveInfinity`, and `NegativeInfinity`, the result string consists exclusively of the symbols defined by the , , and properties, respectively. + +## Modify NumberFormatInfo properties + +You can modify the properties of a object to customize the result string produced in a numeric formatting operation. To do this: + +1. Create a read/write copy of a object whose formatting conventions you want to modify. For more information, see the [Instantiate a NumberFormatInfo object](#instantiate-a-numberformatinfo-object) section. + +2. Modify the property or properties that are used to produce the desired result string. For information about how formatting methods use properties to define result strings, see the [Format strings and NumberFormatInfo properties](#format-strings-and-numberformatinfo-properties) section. + +3. Use the custom object as the argument in calls to formatting methods. + +> [!NOTE] +> Instead of dynamically modifying a culture's property values each time an application is started, you can use the class to define either a custom culture (a culture that has a unique name and that supplements existing cultures) or a replacement culture (one that is used instead of a specific culture). + +The following sections provide some examples. + +### Modify the currency symbol and pattern + +The following example modifies a object that represents the formatting conventions of the en-US culture. It assigns the ISO-4217 currency symbol to the property and defines a pattern for currency values that consists of the currency symbol followed by a space and a numeric value. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/customize_currency1.cs" interactive="try-dotnet" id="Snippet1"::: + +### Format a national identification number + +Many national identification numbers consist exclusively of digits and so can easily be formatted by modifying the properties of a object. For example, a social security number in the United States consists of 9 digits arranged as follows: `XXX-XX-XXXX`. The following example assumes that social security numbers are stored as integer values and formats them appropriately. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/customize_ssn1.cs" interactive="try-dotnet" id="Snippet2"::: + +## Parse numeric strings + +Parsing involves converting the string representation of a number to a number. Each numeric type in .NET includes two overloaded parsing methods: `Parse` and `TryParse`. The `Parse` method converts a string to a number and throws an exception if the conversion fails. The `TryParse` method converts a string to a number, assigns the number to an `out` argument, and returns a value that indicates whether the conversion succeeded. + +The parsing methods implicitly or explicitly use a enumeration value to determine what style elements (such as group separators, a decimal separator, or a currency symbol) can be present in a string if the parsing operation is to succeed. If a value is not provided in the method call, the default is a value that includes the and flags, which specifies that the parsed string can include group symbols, a decimal separator, a negative sign, and white-space characters, or it can be the string representation of a number in exponential notation. + +The parsing methods also implicitly or explicitly use a object that defines the specific symbols and patterns that can occur in the string to be parsed. If a object is not provided, the default is the for the current culture. For more information about parsing, see the individual parsing methods, such as , , , , , and . + +The following example illustrates the culture-sensitive nature of parsing strings. It tries to parse a string that include thousands separators by using the conventions of the en-US, fr-FR, and invariant cultures. A string that includes the comma as a group separator and the period as a decimal separator fails to parse in the fr-FR culture, and a string with white space as a group separator and a comma as a decimal separator fails to parse in the en-US and invariant cultures. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/parse1.cs" interactive="try-dotnet" id="Snippet4"::: + +Parsing generally occurs in two contexts: + +- As an operation that is designed to convert user input into a numeric value. + +- As an operation that is designed to round-trip a numeric value; that is, to deserialize a numeric value that was previously serialized as a string. + +The following sections discuss these two operations in greater detail. + +### Parse user strings + +When you are parsing numeric strings input by the user, you should always instantiate a object that reflects the user's cultural settings. For information about how to instantiate a object that reflects user customizations, see the [Dynamic data](#dynamic-data) section. + +The following example illustrates the difference between a parsing operation that reflects user cultural settings and one that does not. In this case, the default system culture is en-US, but the user has defined "," as the decimal symbol and "." as the group separator in Control Panel, **Region and Language**. Ordinarily, these symbols are reversed in the default en-US culture. When the user enters a string that reflects user settings, and the string is parsed by a object that also reflects user settings (overrides), the parsing operation returns a correct result. However, when the string is parsed by a object that reflects standard en-US cultural settings, it mistakes the comma symbol for a group separator and returns an incorrect result. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/parseuser1.cs" interactive="try-dotnet" id="Snippet5"::: + +### Serialize and deserialize numeric data + +When numeric data is serialized in string format and later deserialized and parsed, the strings should be generated and parsed by using the conventions of the invariant culture. The formatting and parsing operations should never reflect the conventions of a specific culture. If culture-specific settings are used, the portability of the data is strictly limited; it can be successfully deserialized only on a thread whose culture-specific settings are identical to those of the thread on which it was serialized. In some cases, this means that the data cannot even be successfully deserialized on the same system on which it was serialized. + +The following example illustrates what can happen when this principle is violated. Floating-point values in an array are converted to strings when the current thread uses the culture-specific settings of the en-US culture. +The data is then parsed by a thread that uses the culture-specific settings of the pt-BR culture. In this case, although each parsing operation succeeds, the data doesn't round-trip successfully and data corruption occurs. +In other cases, a parsing operation could fail and a exception could be thrown. + +:::code language="csharp" source="./snippets/System.Globalization/NumberFormatInfo/csharp/parsepersisted.cs" interactive="try-dotnet" id="Snippet6"::: diff --git a/docs/fundamentals/runtime-libraries/system-globalization-persiancalendar.md b/docs/fundamentals/runtime-libraries/system-globalization-persiancalendar.md new file mode 100644 index 0000000000000..62e76ed1f9500 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-persiancalendar.md @@ -0,0 +1,42 @@ +--- +title: System.Globalization.PersianCalendar class +description: Learn more about the System.Globalization.PersianCalendar class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +The Persian calendar is used in most countries/regions where Persian is spoken, although some regions use different month names. The Persian calendar is the official calendar of Iran and Afghanistan, and it is one of the alternative calendars in regions such as Kazakhstan and Tajikistan. + +> [!NOTE] +> For information about using the class and the other calendar classes in .NET, see [Working with Calendars](../../standard/datetime/working-with-calendars.md). + +The Persian calendar is a solar Hijri calendar, and starts from the year of the Hijra, which corresponds to 622 C.E. the year when Muhammad (PBUH) migrated from Mecca to Medina. + +The Persian calendar is based on a solar year and is approximately 365 days long. A year cycles through four seasons, and a new year begins when the sun appears to cross the equator from the southern hemisphere to the northern hemisphere as viewed from the center of the Earth. The new year marks the first day of the month of Farvardeen, which is the first day of spring in the northern hemisphere. For example, the date March 21, 2002 C.E. corresponds to the first day of the month of Farvardeen in the year 1381 Anno Persico. + +Each of the first six months in the Persian calendar has 31 days, each of the next five months has 30 days, and the last month has 29 days in a common year and 30 days in a leap year. A leap year is a year that, when divided by 33, has a remainder of 1, 5, 9, 13, 17, 22, 26, or 30. For example, the year 1370 is a leap year because dividing it by 33 yields a remainder of 17. There are approximately eight leap years in every 33-year cycle. + +## The PersianCalendar class and .NET Framework versions + +Starting with .NET Framework 4.6, the class uses the Hijri solar astronomical algorithm rather than an observational algorithm to calculate dates. This makes the implementation consistent with the Persian calendar in use in Iran and Afghanistan, the two countries in which the Persian calendar is in most widespread use. The change affects all apps running on the .NET Framework 4 or later if the .NET Framework 4.6 is installed. + +As a result of the changed algorithm: + +- The two algorithms should return identical results when converting dates between 1800 and 2123 in the Gregorian calendar. + +- The two algorithms may return different results when converting dates before 1800 and after 2123 in the Gregorian calendar. + +- The property value has changed from March 21, 0622 in the Gregorian calendar to March 22, 0622 in the Gregorian calendar. + +- The property value has changed from the 10th day of the 10th month of the year 9378 in the Persian calendar to the 13th day of the 10th month of the year 9378 in the Persian calendar. + +- The method may return a different result than it did previously. + +## Use the PersianCalendar class + +Applications use a object to calculate dates in the Persian calendar or convert Persian dates to and from Gregorian dates. + +You cannot use a object as the default calendar for a culture. The default calendar is specified by the property and must be one of the calendars returned by the property. Currently, the class is not an optional calendar for any culture supported by the class and consequently cannot be a default calendar. diff --git a/docs/fundamentals/runtime-libraries/system-globalization-regioninfo.md b/docs/fundamentals/runtime-libraries/system-globalization-regioninfo.md new file mode 100644 index 0000000000000..67ef3c6bdb99f --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-regioninfo.md @@ -0,0 +1,38 @@ +--- +title: System.Globalization.RegionInfo class +description: Learn more about the System.Globalization.RegionInfo class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +Unlike the class, the class does not represent user preferences and does not depend on the user's language or culture. + +## Names associated with a RegionInfo object + +The name of a object is one of the two-letter codes defined in ISO 3166 for country/region. Case is not significant. The , , and properties return the appropriate codes in uppercase. For the current list of names, see [ISO 3166: Country codes](https://www.iso.org/iso-3166-country-codes.html). + +## Instantiate a RegionInfo object + +To instantiate a object, you pass the constructor either a two-letter region name, such as "US" for the United States, or the name of a specific culture, such as "en-US" for English (United States). However, we recommend that you use a specific culture name instead of a two-letter region name, because a object is not completely language-independent. Several properties, including , , and , depend on culture names. + +The following example illustrates the difference in property values for three objects that represent Belgium. The first is instantiated from a region name (`BE`) only, while the second and third are instantiated from culture names (`fr-BE` for French (Belgium) and `nl-BE` for Dutch (Belgium), respectively). The example uses reflection to retrieve the property values of each object. + +:::code language="csharp" source="./snippets/System.Globalization/RegionInfo/csharp/propertyvalues1.cs" id="Snippet2"::: + +In scenarios such as the following, use culture names instead of country/region names when you instantiate a object: + +- When the language name is of primary importance. For example, for the `es-US` culture name, you'll probably want your application to display "Estados Unidos" instead of "United States". Using the country/region name (`US`) alone yields "United States" regardless of the language, so you should work with the culture name instead. + +- When script differences must be considered. For example, the country/region `AZ` deals with Azerbaijani cultures that have the names `az-Latn-AZ` and `az-Cyrl-AZ`, and the Latin and Cyrillic scripts can be very different for this country/region. + +- When maintenance of detail is important. The values returned by members can differ depending on whether the object was instantiated by using a culture name or a region name. For example, the following table lists the differences in return values when a object is instantiated by using the "US" region, the "en-US" culture, and the "es-US" culture. + + | Member | "US" | "en-US" | "es-US" | + |-----------------------------------------------------------|-----------------|-----------------|-------------------| + | | `US Dollar` | `US Dollar` | `Dólar de EE.UU.` | + | | `US` | `en-US` | `es-US` | + | | `United States` | `United States` | `Estados Unidos` | + | | `US` | `en-US` | `es-US` | diff --git a/docs/fundamentals/runtime-libraries/system-globalization-sortkey.md b/docs/fundamentals/runtime-libraries/system-globalization-sortkey.md new file mode 100644 index 0000000000000..6a3be9b7b0fc3 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-sortkey.md @@ -0,0 +1,46 @@ +--- +title: System.Globalization.SortKey class +description: Learn more about the System.Globalization.SortKey class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +A culture-sensitive comparison of two strings depends on each character in the strings having several categories of sort weights, including script, alphabetic, case, and diacritic weights. A sort key serves as the repository of these weights for a particular string. + +The method returns an instance of the class that reflects the culture-sensitive mapping of characters in a specified string. The value of a object is its key data, which is returned by the property. This key data consists of a series of bytes that encode the string, culture-specific sorting rules, and user-specified comparison options. A comparison using sort keys consists of a bitwise comparison of the corresponding key data in each sort key. For example, if you create a sort key by calling the method with a value of , a string comparison operation that uses the sort key is case-insensitive. + +After you create a sort key for a string, you compare sort keys by calling the static method. This method performs a simple byte-by-byte comparison, so it is much faster than the or method. + +> [!NOTE] +> You can download the [Sorting Weight Tables](https://www.microsoft.com/download/details.aspx?id=10921), a set of text files that contain information on the character weights used in sorting and comparison operations for Windows operating systems, the [Default Unicode Collation Element Table](https://www.unicode.org/Public/UCA/latest/allkeys.txt), the sort weight table for Linux and macOS. + +## Performance considerations + +When performing a string comparison, the and methods yield the same results, but they target different scenarios. + +At a high level, the method generates the sort key for each string, performs the comparison, and then discards the sort key and returns the result of the comparison. However, the method actually doesn't generate an entire sort key to perform the comparison. Instead, the method generates the key data for each text element (that is, base character, surrogate pair, or combining character sequence) in each string. The method then compares the key data for the corresponding text elements. The operation terminates as soon as the ultimate result of the comparison is determined. Sort key information is computed, but no object is created. This strategy is economical in terms of performance if both strings are compared once, but becomes expensive if the same strings are compared many times. + +The method requires generation of a object for each string before performing the comparison. This strategy is expensive in terms of performance for the first comparison because of the time and memory invested to generate the objects. However, it becomes economical if the same sort keys are compared many times. + +For example, suppose you write an application that searches a database table for the row in which the string-based index column matches a specified search string. The table contains thousands of rows, and comparing the search string to the index in each row will take a long time. Therefore, when the application stores a row and its index column, it also generates and stores the sort key for the index in a column dedicated to improving search performance. When the application searches for a target row, it compares the sort key for the search string to the sort key for the index string, instead of comparing the search string to the index string. + +## Security considerations + +The method returns a object with the value based on a specified string and value, and the culture associated with the underlying object. If a security decision depends on a string comparison or case change, you should use the method of the invariant culture to ensure that the behavior of the operation is consistent, regardless of the culture settings of the operating system. + +Use the following steps to obtain a sort key: + +1. Retrieve the invariant culture from the property. + +2. Retrieve a object for the invariant culture from the property. + +3. Call the method. + +Working with the value of a object is equivalent to calling the Windows `LCMapString` method with the LCMAP_SORTKEY value specified. However, for the object, the sort keys for English characters precede the sort keys for Korean characters. + + objects can be serialized, but only so that they can cross objects. If an application serializes a object, the application must regenerate all the sort keys when there is a new version of the .NET Framework. + +For more information about sort keys, see Unicode Technical Standard #10, "Unicode Collation Algorithm" on the [Unicode Consortium website](https://go.microsoft.com/fwlink/?linkid=37123). diff --git a/docs/fundamentals/runtime-libraries/system-globalization-sortversion.md b/docs/fundamentals/runtime-libraries/system-globalization-sortversion.md new file mode 100644 index 0000000000000..75ed8bec43b9a --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-globalization-sortversion.md @@ -0,0 +1,51 @@ +--- +title: System.Globalization.SortVersion class +description: Learn more about the System.Globalization.SortVersion class. +ms.date: 12/28/2023 +ms.topic: conceptual +--- +# class + +[!INCLUDE [context](includes/context.md)] + +## Sorting and string comparison in .NET Framework + +Through .NET Framework 4, each version of .NET Framework included tables that contained sort weights and data on string normalization and that are based on a particular version of Unicode. In .NET Framework 4.5 and later versions, the presence of these tables depends on the operating system: + +- On Windows 7 and previous versions, the tables continue to be used for comparing and ordering strings. +- On Windows 8, .NET Framework delegates string comparison and ordering operations to the operating system. + +Consequently, the result of a string comparison can depend not only on the .NET Framework version, but also on the operating system version, as the following table shows. Note that this list of supported Unicode versions applies to character comparison and sorting only; it does not apply to classification of Unicode characters by category. + +| .NET Framework version | Operating system | Unicode version | +|------------------------|------------------------------|-----------------| +| 4 | All operating systems | Unicode 5.0 | +| 4.5 and later versions | Windows 7 | Unicode 5.0 | +| 4.5 and later versions | Windows 8 and later versions | Unicode 6.0 | + +On Windows 8, because the version of Unicode used in string comparison and ordering depends on the version of the operating system, the results of string comparison may differ even for applications that run on a specific version of .NET Framework. + +## Sorting and string comparison in .NET Core + +All versions of .NET (Core) rely on the underlying operating system when performing string comparisons. Therefore, the results of a string comparison or the order in which strings are sorted depends on the version of Unicode used by the operating system when performing the comparison. On Linux, macOS, and Windows 10 and later versions, [International Components for Unicode](https://icu.unicode.org/) libraries provide the implementation for comparison and sorting APIs. + +## Use the SortVersion class + +The class provides information about the Unicode version used by .NET for string comparison and ordering. It enables developers to write applications that can detect and successfully handle changes in the version of Unicode that is used to compare and sort an application's strings. + +You can instantiate a object in two ways: + +- By calling the constructor, which instantiates a new object based on a version number and sort ID. This constructor is most useful when recreating a object from saved data. +- By retrieving the value of the property. This property provides information about the Unicode version used by the .NET implementation on which the application is running. + +The class has two properties, and , that indicate the Unicode version and the specific culture used for string comparison. The property is an arbitrary numeric value that reflects the Unicode version used for string comparison, and the property is an arbitrary that reflects the culture whose conventions are used for string comparison. The values of these two properties are important only when you compare two objects by using the method, the operator, or the operator. + +You typically use a object when saving or retrieving some form of culture-sensitive, ordered string data, such as indexes or the literal strings themselves. This requires the following steps: + +1. When the ordered string data is saved, the and property values are also saved. + +2. When the ordered string data is retrieved, you can recreate the object used for ordering the strings by calling the constructor. + +3. This newly instantiated object is compared with a object that reflects the culture whose conventions are used to order the string data. + +4. If the two objects are not equal, the string data must be reordered. diff --git a/docs/fundamentals/toc.yml b/docs/fundamentals/toc.yml index f0083d32ee7bf..1c1f428943152 100644 --- a/docs/fundamentals/toc.yml +++ b/docs/fundamentals/toc.yml @@ -923,12 +923,6 @@ items: - name: Globalization and ICU href: ../core/extensions/globalization-icu.md displayName: globalization,icu,culture - - name: Localizability review - href: ../core/extensions/localizability-review.md - displayName: localizability,localization,localization review,localizability review - - name: Localization - href: ../core/extensions/localization.md - displayName: localization,localization review,localizability review - name: Culture-insensitive string operations items: - name: Overview @@ -943,6 +937,34 @@ items: href: ../core/extensions/performing-culture-insensitive-string-operations-in-arrays.md - name: Best practices for developing world-ready apps href: ../core/extensions/best-practices-for-developing-world-ready-apps.md + - name: Localizability review + href: ../core/extensions/localizability-review.md + displayName: localizability,localization,localization review,localizability review + - name: Localization + href: ../core/extensions/localization.md + displayName: localization,localization review,localizability review + - name: Supplemental API remarks + items: + - name: CompareInfo + href: runtime-libraries/system-globalization-compareinfo.md + - name: CompareOptions + href: runtime-libraries/system-globalization-compareoptions.md + - name: CultureAndRegionInfoBuilder + href: runtime-libraries/system-globalization-cultureandregioninfobuilder.md + - name: CultureInfo + href: runtime-libraries/system-globalization-cultureinfo.md + - name: DateTimeFormatInfo + href: runtime-libraries/system-globalization-datetimeformatinfo.md + - name: NumberFormatInfo + href: runtime-libraries/system-globalization-numberformatinfo.md + - name: PersianCalendar + href: runtime-libraries/system-globalization-persiancalendar.md + - name: RegionInfo + href: runtime-libraries/system-globalization-regioninfo.md + - name: SortKey + href: runtime-libraries/system-globalization-sortkey.md + - name: SortVersion + href: runtime-libraries/system-globalization-sortversion.md - name: Resources in .NET apps items: - name: Overview diff --git a/docs/standard/io/how-to-use-named-pipes-for-network-interprocess-communication.md b/docs/standard/io/how-to-use-named-pipes-for-network-interprocess-communication.md index cad0a749ddd7c..061b5cb917247 100644 --- a/docs/standard/io/how-to-use-named-pipes-for-network-interprocess-communication.md +++ b/docs/standard/io/how-to-use-named-pipes-for-network-interprocess-communication.md @@ -19,7 +19,10 @@ ms.assetid: 4e4d7e64-9f1b-4026-98f7-20488ac7b42b # How to: Use Named Pipes for Network Interprocess Communication Named pipes provide interprocess communication between a pipe server and one or more pipe clients. They offer more functionality than anonymous pipes, which provide interprocess communication on a local computer. Named pipes support full duplex communication over a network and multiple server instances, message-based communication, and client impersonation, which enables connecting processes to use their own set of permissions on remote servers. - + +> [!IMPORTANT] +> .NET on Linux uses Unix Domain Sockets (UDS) for the implementation of these APIs. + To implement name pipes, use the and classes. ## Example 1 diff --git a/samples/snippets/fsharp/getting-started/pig-latin.fs b/samples/snippets/fsharp/getting-started/pig-latin.fs index 5f96886d99d2b..503e9825f1302 100644 --- a/samples/snippets/fsharp/getting-started/pig-latin.fs +++ b/samples/snippets/fsharp/getting-started/pig-latin.fs @@ -4,7 +4,7 @@ module PigLatin = let toPigLatin (word: string) = let isVowel (c: char) = match c with - | 'a' | 'e' | 'i' |'o' |'u' + | 'a' | 'e' | 'i' | 'o' | 'u' | 'A' | 'E' | 'I' | 'O' | 'U' -> true |_ -> false diff --git a/samples/snippets/fsharp/getting-started/to-pig-latin.fsx b/samples/snippets/fsharp/getting-started/to-pig-latin.fsx index 4495cd9c0cb7d..fb38f3688e5de 100644 --- a/samples/snippets/fsharp/getting-started/to-pig-latin.fsx +++ b/samples/snippets/fsharp/getting-started/to-pig-latin.fsx @@ -1,7 +1,7 @@ let toPigLatin (word: string) = let isVowel (c: char) = match c with - | 'a' | 'e' | 'i' |'o' |'u' + | 'a' | 'e' | 'i' | 'o' | 'u' | 'A' | 'E' | 'I' | 'O' | 'U' -> true |_ -> false