Skip to content

Commit 1bf68ad

Browse files
authored
remove binary serialization examples from globalization article (#34842)
1 parent 392bb36 commit 1bf68ad

File tree

27 files changed

+448
-711
lines changed

27 files changed

+448
-711
lines changed

docs/core/extensions/globalization.md

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ The use of Unicode ensures that the same code units always map to the same chara
4545
Even if you are developing an app that targets a single culture or region, you should use resource files to store strings and other resources that are displayed in the user interface. You should never add them directly to your code. Using resource files has a number of advantages:
4646

4747
- All the strings are in a single location. You don't have to search throughout your source code to identify strings to modify for a specific language or culture.
48-
49-
- There is no need to duplicate strings. Developers who don't use resource files often define the same string in multiple source code files. This duplication increases the probability that one or more instances will be overlooked when a string is modified.
50-
48+
- There's no need to duplicate strings. Developers who don't use resource files often define the same string in multiple source code files. This duplication increases the probability that one or more instances will be overlooked when a string is modified.
5149
- You can include non-string resources, such as images or binary data, in the resource file instead of storing them in a separate standalone file, so they can be retrieved easily.
5250

5351
Using resource files has particular advantages if you are creating a localized app. When you deploy resources in satellite assemblies, the common language runtime automatically selects a culture-appropriate resource based on the user's current UI culture as defined by the <xref:System.Globalization.CultureInfo.CurrentUICulture%2A?displayProperty=nameWithType> property. As long as you provide an appropriate culture-specific resource and correctly instantiate a <xref:System.Resources.ResourceManager> object or use a strongly typed resource class, the runtime handles the details of retrieving the appropriate resources.
@@ -155,9 +153,7 @@ You should never persist date and time data in a format that can vary by culture
155153
You can avoid this problem in any of three ways:
156154

157155
- Serialize the date and time in binary format rather than as a string.
158-
159156
- Save and parse the string representation of the date and time by using a custom format string that is the same regardless of the user's culture.
160-
161157
- Save the string by using the formatting conventions of the invariant culture.
162158

163159
The following example illustrates the last approach. It uses the formatting conventions of the invariant culture returned by the static <xref:System.Globalization.CultureInfo.InvariantCulture%2A?displayProperty=nameWithType> property.
@@ -169,7 +165,11 @@ The following example illustrates the last approach. It uses the formatting conv
169165

170166
A date and time value can have multiple interpretations, ranging from a general time ("The stores open on January 2, 2013, at 9:00 A.M.") to a specific moment in time ("Date of birth: January 2, 2013 6:32:00 A.M."). When a time value represents a specific moment in time and you restore it from a serialized value, you should ensure that it represents the same moment in time regardless of the user's geographical location or time zone.
171167

172-
The following example illustrates this problem. It saves a single local date and time value as a string in three [standard formats](../../standard/base-types/standard-date-and-time-format-strings.md) ("G" for general date long time, "s" for sortable date/time, and "o" for round-trip date/time) as well as in binary format.
168+
The following example illustrates this problem. It saves a single local date and time value as a string in three [standard formats](../../standard/base-types/standard-date-and-time-format-strings.md):
169+
170+
- "G" for general date long time.
171+
- "s" for sortable date/time.
172+
- "o" for round-trip date/time.
173173

174174
[!code-csharp[Conceptual.Globalization#10](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.globalization/cs/dates4.cs#10)]
175175
[!code-vb[Conceptual.Globalization#10](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.globalization/vb/dates4.vb#10)]
@@ -180,30 +180,22 @@ When the data is restored on a system in the same time zone as the system on whi
180180
'3/30/2013 6:00:00 PM' --> 3/30/2013 6:00:00 PM Unspecified
181181
'2013-03-30T18:00:00' --> 3/30/2013 6:00:00 PM Unspecified
182182
'2013-03-30T18:00:00.0000000-07:00' --> 3/30/2013 6:00:00 PM Local
183-
184-
3/30/2013 6:00:00 PM Local
185183
```
186184

187185
However, if you restore the data on a system in a different time zone, only the date and time value that was formatted with the "o" (round-trip) standard format string preserves time zone information and therefore represents the same instant in time. Here's the output when the date and time data is restored on a system in the Romance Standard Time zone:
188186

189187
```console
190-
'3/30/2013 6:00:00 PM' --> 3/30/2013 6:00:00 PM Unspecified
191-
'2013-03-30T18:00:00' --> 3/30/2013 6:00:00 PM Unspecified
192-
'2013-03-30T18:00:00.0000000-07:00' --> 3/31/2013 3:00:00 AM Local
193-
194-
3/30/2013 6:00:00 PM Local
188+
'3/30/2023 6:00:00 PM' --> 3/30/2023 6:00:00 PM Unspecified
189+
'2023-03-30T18:00:00' --> 3/30/2023 6:00:00 PM Unspecified
190+
'2023-03-30T18:00:00.0000000-07:00' --> 3/31/2023 3:00:00 AM Local
195191
```
196192

197193
To accurately reflect a date and time value that represents a single moment of time regardless of the time zone of the system on which the data is deserialized, you can do any of the following:
198194

199195
- Save the value as a string by using the "o" (round-trip) standard format string. Then deserialize it on the target system.
200-
201196
- Convert it to UTC and save it as a string by using the "r" (RFC1123) standard format string. Then deserialize it on the target system and convert it to local time.
202-
203197
- Convert it to UTC and save it as a string by using the "u" (universal sortable) standard format string. Then deserialize it on the target system and convert it to local time.
204198

205-
- Convert it to UTC and save it in binary format. Then deserialize it on the target system and convert it to local time.
206-
207199
The following example illustrates each technique.
208200

209201
[!code-csharp[Conceptual.Globalization#11](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.globalization/cs/dates8.cs#11)]
@@ -212,11 +204,9 @@ The following example illustrates each technique.
212204
When the data is serialized on a system in the Pacific Standard Time zone and deserialized on a system in the Romance Standard Time zone, the example displays the following output:
213205

214206
```console
215-
'2013-03-30T18:00:00.0000000-07:00' --> 3/31/2013 3:00:00 AM Local
216-
'Sun, 31 Mar 2013 01:00:00 GMT' --> 3/31/2013 3:00:00 AM Local
217-
'2013-03-31 01:00:00Z' --> 3/31/2013 3:00:00 AM Local
218-
219-
3/31/2013 3:00:00 AM Local
207+
'2023-03-30T18:00:00.0000000-07:00' --> 3/31/2023 3:00:00 AM Local
208+
'Sun, 31 Mar 2023 01:00:00 GMT' --> 3/31/2023 3:00:00 AM Local
209+
'2023-03-31 01:00:00Z' --> 3/31/2023 3:00:00 AM Local
220210
```
221211

222212
For more information, see [Convert times between time zones](../../standard/datetime/converting-between-time-zones.md).
@@ -233,9 +223,7 @@ For example, the transition from Pacific Standard Time to Pacific Daylight Time
233223
To ensure that an arithmetic operation on date and time values produces accurate results, follow these steps:
234224

235225
1. Convert the time in the source time zone to UTC.
236-
237226
2. Perform the arithmetic operation.
238-
239227
3. If the result is a date and time value, convert it from UTC to the time in the source time zone.
240228

241229
The following example is similar to the previous example, except that it follows these three steps to correctly add 48 hours to March 9, 2013 at 10:30 A.M.
@@ -268,13 +256,11 @@ The handling of numbers depends on whether they are displayed in the user interf
268256
269257
### Display numeric values
270258

271-
Typically, when numbers are displayed in the user interface, you should use the formatting conventions of the user's culture, which is defined by the <xref:System.Globalization.CultureInfo.CurrentCulture%2A?displayProperty=nameWithType> property and by the <xref:System.Globalization.NumberFormatInfo> object returned by the `CultureInfo.CurrentCulture.NumberFormat` property. The formatting conventions of the current culture are automatically used when you format a date by using any of the following methods:
272-
273-
- The parameterless `ToString` method of any numeric type
259+
Typically, when numbers are displayed in the user interface, you should use the formatting conventions of the user's culture, which is defined by the <xref:System.Globalization.CultureInfo.CurrentCulture%2A?displayProperty=nameWithType> property and by the <xref:System.Globalization.NumberFormatInfo> object returned by the `CultureInfo.CurrentCulture.NumberFormat` property. The formatting conventions of the current culture are automatically used when you format a date in the following ways:
274260

275-
- The `ToString(String)` method of any numeric type, which includes a format string as an argument
276-
277-
- The [composite formatting](../../standard/base-types/composite-formatting.md) feature, when it is used with numeric values
261+
- Using the parameterless `ToString` method of any numeric type.
262+
- Using the `ToString(String)` method of any numeric type, which includes a format string as an argument.
263+
- Using [composite formatting](../../standard/base-types/composite-formatting.md) with numeric values.
278264

279265
The following example displays the average temperature per month in Paris, France. It first sets the current culture to French (France) before displaying the data, and then sets it to English (United States). In each case, the month names and temperatures are displayed in the format that is appropriate for that culture. Note that the two cultures use different decimal separators in the temperature value. Also note that the example uses the "MMMM" custom date and time format string to display the full month name, and that it allocates the appropriate amount of space for the month name in the result string by determining the length of the longest month name in the <xref:System.Globalization.DateTimeFormatInfo.MonthNames%2A?displayProperty=nameWithType> array.
280266

@@ -291,17 +277,9 @@ You should never persist numeric data in a culture-specific format. This is a co
291277
To avoid this problem, you can use one of these techniques:
292278

293279
- Save and parse the string representation of the number by using a custom format string that is the same regardless of the user's culture.
294-
295280
- Save the number as a string by using the formatting conventions of the invariant culture, which is returned by the <xref:System.Globalization.CultureInfo.InvariantCulture%2A?displayProperty=nameWithType> property.
296281

297-
- Serialize the number in binary instead of string format.
298-
299-
The following example illustrates the last approach. It serializes the array of <xref:System.Double> values, and then deserializes and displays them by using the formatting conventions of the English (United States) and French (France) cultures.
300-
301-
[!code-csharp[Conceptual.Globalization#7](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.globalization/cs/numbers3.cs#7)]
302-
[!code-vb[Conceptual.Globalization#7](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.globalization/vb/numbers3.vb#7)]
303-
304-
Serializing currency values is a special case. Because a currency value depends on the unit of currency in which it is expressed; it makes little sense to treat it as an independent numeric value. However, if you save a currency value as a formatted string that includes a currency symbol, it cannot be deserialized on a system whose default culture uses a different currency symbol, as the following example shows.
282+
Serializing currency values is a special case. Because a currency value depends on the unit of currency in which it's expressed, it makes little sense to treat it as an independent numeric value. However, if you save a currency value as a formatted string that includes a currency symbol, it cannot be deserialized on a system whose default culture uses a different currency symbol, as the following example shows.
305283

306284
[!code-csharp[Conceptual.Globalization#16](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.globalization/cs/currency1.cs#16)]
307285
[!code-vb[Conceptual.Globalization#16](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.globalization/vb/currency1.vb#16)]

samples/snippets/csharp/VS_Snippets_CLR/conceptual.globalization/cs/codepages1.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
public class Example
77
{
8-
public static void Main()
8+
public static void CodePages()
99
{
1010
// Represent Greek uppercase characters in code page 737.
1111
char[] greekChars =
@@ -43,6 +43,7 @@ public static void Main()
4343
Console.WriteLine(data);
4444
}
4545
}
46+
4647
// The example displays the following output:
4748
// ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ
4849
// €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’""•–—

samples/snippets/csharp/VS_Snippets_CLR/conceptual.globalization/cs/currency2.cs

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,47 @@
11
// <Snippet17>
22
using System;
33
using System.Globalization;
4-
using System.IO;
5-
using System.Runtime.Serialization.Formatters.Binary;
4+
using System.Text.Json;
65
using System.Threading;
76

87
public class Example2
98
{
10-
public static void Main2()
11-
{
12-
// Display the currency value.
13-
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
14-
Decimal value = 16039.47m;
15-
Console.WriteLine("Current Culture: {0}", CultureInfo.CurrentCulture.DisplayName);
16-
Console.WriteLine("Currency Value: {0:C2}", value);
9+
public static void Main2()
10+
{
11+
// Display the currency value.
12+
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
13+
Decimal value = 16039.47m;
14+
Console.WriteLine($"Current Culture: {CultureInfo.CurrentCulture.DisplayName}");
15+
Console.WriteLine($"Currency Value: {value:C2}");
1716

18-
// Serialize the currency data.
19-
BinaryFormatter bf = new BinaryFormatter();
20-
FileStream fw = new FileStream("currency.dat", FileMode.Create);
21-
CurrencyValue data = new CurrencyValue(value, CultureInfo.CurrentCulture.Name);
22-
bf.Serialize(fw, data);
23-
fw.Close();
24-
Console.WriteLine();
17+
// Serialize the currency data.
18+
CurrencyValue data = new()
19+
{
20+
Amount = value,
21+
CultureName = CultureInfo.CurrentCulture.Name
22+
};
23+
string serialized = JsonSerializer.Serialize(data);
24+
Console.WriteLine();
2525

26-
// Change the current culture.
27-
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
28-
Console.WriteLine("Current Culture: {0}", CultureInfo.CurrentCulture.DisplayName);
26+
// Change the current culture.
27+
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
28+
Console.WriteLine($"Current Culture: {CultureInfo.CurrentCulture.DisplayName}");
2929

30-
// Deserialize the data.
31-
FileStream fr = new FileStream("currency.dat", FileMode.Open);
32-
CurrencyValue restoredData = (CurrencyValue) bf.Deserialize(fr);
33-
fr.Close();
30+
// Deserialize the data.
31+
CurrencyValue restoredData = JsonSerializer.Deserialize<CurrencyValue>(serialized);
3432

35-
// Display the original value.
36-
CultureInfo culture = CultureInfo.CreateSpecificCulture(restoredData.CultureName);
37-
Console.WriteLine("Currency Value: {0}", restoredData.Amount.ToString("C2", culture));
38-
}
33+
// Display the round-tripped value.
34+
CultureInfo culture = CultureInfo.CreateSpecificCulture(restoredData.CultureName);
35+
Console.WriteLine($"Currency Value: {restoredData.Amount.ToString("C2", culture)}");
36+
}
3937
}
4038

41-
[Serializable] internal struct CurrencyValue
39+
internal struct CurrencyValue
4240
{
43-
public CurrencyValue(Decimal amount, string name)
44-
{
45-
this.Amount = amount;
46-
this.CultureName = name;
47-
}
48-
49-
public Decimal Amount;
50-
public string CultureName;
41+
public decimal Amount { get; set; }
42+
public string CultureName { get; set; }
5143
}
44+
5245
// The example displays the following output:
5346
// Current Culture: English (United States)
5447
// Currency Value: $16,039.47

samples/snippets/csharp/VS_Snippets_CLR/conceptual.globalization/cs/dates1.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,26 @@
55

66
public class Example3
77
{
8-
static DateTime[] dates = { new DateTime(2012, 10, 11, 7, 06, 0),
8+
static DateTime[] dates = { new DateTime(2012, 10, 11, 7, 06, 0),
99
new DateTime(2012, 10, 11, 18, 19, 0) };
1010

11-
public static void Main3()
12-
{
13-
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("hr-HR");
14-
ShowDayInfo();
15-
Console.WriteLine();
16-
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
17-
ShowDayInfo();
18-
}
11+
public static void Main3()
12+
{
13+
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("hr-HR");
14+
ShowDayInfo();
15+
Console.WriteLine();
16+
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
17+
ShowDayInfo();
18+
}
1919

20-
private static void ShowDayInfo()
21-
{
22-
Console.WriteLine("Date: {0:D}", dates[0]);
23-
Console.WriteLine(" Sunrise: {0:T}", dates[0]);
24-
Console.WriteLine(" Sunset: {0:T}", dates[1]);
25-
}
20+
private static void ShowDayInfo()
21+
{
22+
Console.WriteLine("Date: {0:D}", dates[0]);
23+
Console.WriteLine(" Sunrise: {0:T}", dates[0]);
24+
Console.WriteLine(" Sunset: {0:T}", dates[1]);
25+
}
2626
}
27+
2728
// The example displays the following output:
2829
// Date: 11. listopada 2012.
2930
// Sunrise: 7:06:00

0 commit comments

Comments
 (0)