Core NET
Core NET
CONTENTS INCLUDE:
Core .NET
n
Common .NET Types
n
Formatting Strings
n
Declaring Events
n
Generics
Query Expressions (C# 3)
By Jon Skeet
n
n
Tips and more...
The .NET Framework has been growing steadily since its birth— One common task which always has me reaching for MSDN
the API for .NET 3.5 is far bigger than that of .NET 1.0. With so is working out how to format numbers, dates and times as
much to remember, you’ll find this refcard useful for those core strings. There are two ways of formatting in .NET: you can
pieces of information which you need so often but which (if call ToString directly on the item you wish to format, passing
you’re like me) you can never quite recall without looking them in just a format string or you can use composite formatting
up—topics like string formatting, and how to work with dates with a call to String.Format to format more than one item
and times effectively. This reference card deals only with the at a time, or mix data and other text. In either case you can
core of .NET, making it applicable for whatever kind of project
usually specify an IFormatProvider (such as CultureInfo) to help
you’re working on.
with internationalization. Many other methods in the .NET
Framework also work with composite format strings, such as
COMMON .NET TYPES Console.WriteLine and StringBuilder.AppendFormat.
The .NET Framework has a massive set of types in it, but some Composite format strings consist of normal text and format
are so important that C# and VB have built-in keywords for items containing an index and optionally an alignment and
them, as listed in table 1. a format string. Figure 1 shows a sample of using composite
format string, with each element labeled.
C# Alias VB Keyword .NET Type Size(bytes) Object list
object Object System.Object 12 (8 bytes are normal overhead for all
(items to be
reference types) Method call Composite format string formatted)
www.dzone.com
Apart from Object and String, all the types above are value Get More Refcardz
types. When choosing between the three floating point types (They’re free!)
(Single, Double and Decimal):
n Authoritative content
n For financial calculations (i.e. when dealing with money),
use Decimal
n Designed for developers
n Written by top experts
n For scientific calculations (i.e. when dealing with physical n Latest tools & technologies
quantities with theoretically infinite precision, such as
Core .NET
spaces to the left. The effect of the format string depends on 0 Zero placeholder Always formatted as 0 or a digit from the original number
the type of item being formatted. To include a brace as normal # Decimal Formatted as a digit when it’s a significant digit in the
placeholder number, or omitted otherwise
text in a composite format string (instead of it indicating the
. Decimal point Formatted as the decimal point for the current
beginning or end of a format item), just double it. For example, IFormatProvider
the result of String.Format("{{0}}") is "{0}". , Thousands When used between digit or zero placeholders,
separator and formatted as the group separator for the current
Numeric format strings number scaling IFormatProvider. When it’s used directly before a
specifier decimal point (or an implicit decimal point) each
Numbers can be formatted in two ways: with standard or comma effectively means “divide by a thousand”.
custom format strings. The standard ones allow some flexibility % Percentage Formatted as the percent symbol for the current
in terms of the precision and style, but the custom ones can be placeholder IFormatProvider, and also multiplies the number by 100
used for very specific formats. ‰ (\u2030) Per mille Similar to the percentage placeholder, but the
placeholder number is multiplied by 1000 instead of 100, and the
per mille symbol for the culture is used instead of
Standard numeric format strings the percent symbol.
Standard numeric format strings all take the form of a single E0, e0, Scientific Formats the number with scientific (exponential)
letter (the format specifier) and then optionally one or two E+0, e+0, notation notation. The number of 0s indicates the minimum
E-0, or e-0 number of digits to use when expressing the exponent.
digits (the precision). For example, a format string of N5 has For E+0 and e+0, the exponent’s sign is always
expressed; otherwise it’s only expressed for
N as the format specifier and 5 as the precision. The exact negative exponents.
meaning of the precision depends on the format specifier, " or ' Quoting for Text between quotes is formatted exactly as it
as described in table 2. If no precision is specified a suitable literals appears in the format string (i.e. it’s not interpreted
as a format pattern)
default is used based on the current IFormatProvider.
; Section A format string can consist of up to three sections,
separator separated by semi-colons. If only a single section is
Format Description Precision Examples (with US present, it is used for all numbers. If two sections are
English IFormatProvider) present, the first is used for positive numbers and
zero; the second is used for negative numbers. If
C or c Currency – exact Number of 123.4567, “c” => three sections are present, they are used for positive,
format is specified by decimal places “$123.46” negative and zero numbers respectively.
NumberFormatInfo 123.4567, “c3” =>
“$123.457” \c Single-character Escapes a single character, i.e. the character c is
escape displayed verbatim
D or d Decimal (integer types Minimum number 123, “d5” => “00123”
only) of digits 123, “d2” => “123” Table 3. Custom numeric format specifiers
E or e Scientific – used to Number of digits 123456, “e2” =>
express very large after the decimal “1.23e+005” Table 4 shows examples of custom numeric format strings,
or small numbers in point 123456, “E4” => when formatted with a US English format provider.
exponential format. “1.2345E+005”
F or f Fixed point Number of 123.456, “f2” => “123.46” Number Format String Output Notes
decimal places 123.4, “f3” => “123.400” 123 ####.00# 123.00 0 forces a digit; # doesn’t
G or g General—chooses Depends on 123.4, “g2” => “1.2e+02” 12345.6789 ####.00# 12345.679 Value is rounded to 3 decimal places
fixed or scientific exact format used 123.4, “g6” => “123.4”
notation based on (see http://msdn. 123.400m, “g” => 1234 0,0.# 1,234 Decimal point is omitted when
number type and microsoft.com/ “123.400” not required
precision en-us/library/
dwhawy9k.aspx 1234 0,.#### 1.234 Value has been divided by 1000
for details)
0.35 0.00% 35.00% Value has been multiplied by 100
N or n Number—decimal Number of 1234.567, “n2” => 0.0234 0.0\u2030 23.4‰
form including decimal places “1,234.57”
thousands indicators 0.1234 0.00E0 1.23E-1 Exponent specified with single digit
(e.g. commas)
1234 0.00e00 1.23e03 Exponent is specified with two digits,
P or p Percentage—number Number of 0.1234, “p1” => “12.3 %” but sign is omitted
is multiplied by 100 decimal places
1234 ##'text0'### 1text0234 The text0 part is not parsed as a
and percentage sign is
applied format pattern
Table 2. Standard numeric format strings Date and time format strings
Dates and times tend to have more cultural sensitivity than
Custom numeric format strings numbers—the ordering of years, months and days in dates
To format numbers in a custom fashion, you provide a varies between cultures, as do the names of months and so
pattern to the formatter, consisting of format specifiers forth. As with numbers, .NET allows both standard and custom
as shown in table 3. format strings for dates and times.
Standard date and time format strings Custom date and time format strings, continued
Standard date and time format strings are always a single
Format Meaning Notes and variance by repetition
character. Any format string which is longer than that (including Specifier
whitespace) is interpreted as a custom format string. The round- t, tt AM/PM t First character only (e.g. “A” or “P”)
designator tt Full designator (e.g. “AM” or “PM”)
trip (o or O), RFC1123 (r or R), sortable (s) and universal sortable
y ... yyyyy Year y 0-99 (least significant two digits are used)
(u) format specifiers are culturally invariant—in other words, they yy 00-99 (least significant two digits are used)
yyy 000-9999 (three or four digits as necessary)
will produce the same output whichever IFormatProvider is used. yyyy 0000-9999
Table 5 lists all of the standard date and time format specifiers. yyyyy 00000-99999
z ... zzz Offset from z -12 to +13, single or double digit
Format Description Example (US English) UTC (of local zz -12 to +13, always double digit (e.g. +05)
Specifier operating system) zzz -12:00 to +13:00, hours and minutes
d Short date pattern 5/30/2008 : Time separator Culture-specific symbol used to separate hours from
minutes, etc.
D Long date pattern Friday, May 30, 2008
/ Date separator Culture-specific symbol used to separate months from
f Full date/time pattern (short time) Friday, May 30, 2008 8:40 PM
days, etc.
F Full date/time pattern (long time) Friday, May 30, 2008 8:40:36 PM
' Quoting for literals Text between two apostrophes is displayed verbatim.
g General date/time pattern (short time) 5/30/2008 8:40 PM
%c Single custom Uses c as a custom format specifier; used to force a
G General date/time pattern (long time) 5/30/2008 8:40:36 PM format specifier pattern to be interpreted as a custom instead of a
M or m Month day pattern May 30 standard format specifier.
\c Single-character Escapes a single character, i.e. the character c is
O or o Round-trip pattern 2008-05-30T20:40:36.8460000+01:00
escape displayed verbatim.
R or r RFC1123 pattern Fri, 30 May 2008 19:40:36 GMT
(Assumes UTC: caller must convert.) Table 6. Custom date and time format specifiers, continued
s Sortable date pattern 2008-05-30T20:40:36
(ISO 8601 compliant) Typically only years within the range 1-9999 can be represented,
t Short time pattern 8:40 PM but there are some exceptions due to cultural variations. See
T Long time pattern 8:40:36 PM http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx for
u Universal sortable date pattern 2008-05-30 19:40:36Z more details on this and all of the formatting topics.
(Assumes UTC: caller must convert.)
U Universal full date/time pattern Friday, May 30, 2008 7:40:36 PM Table 7 shows examples of custom date and time format strings,
(Format automatically converts to UTC.)
when formatted with a US English format provider. (The date
Y or y Year month pattern May, 2008
and time in question is the same one used to demonstrate
Table 5. Standard date and time format specifiers
the standard format strings.)
Custom date and time format strings Format String Output Notes
As with numbers, custom date and time format strings form yyyy/MM/dd’T’HH:mm:ss.fff 2008/05/30T20:40:36.846 T is quoted for clarity only—T is
not a format specifier, so would
patterns which are used to build up the result. Many of the format have been output anyway.
specifiers act differently depending on the number of times d MMMM yy h:mm tt 30 May 08 8:40 PM 12 hour clock, single digit used
they’re repeated. For example, ‘d’ is used to indicate the day—for HH:mm:sszzz 20:40:36+01:00 24 hour clock, always two digits
a date falling on a Friday and the 5th day of the month, “d” (in yyyy g 2008 A.D. Rarely used—
era is usually implicit
a custom format string) would produce “5”, “dd” would produce
yyyyMMddHHmmssfff 20080530204036846 Not very readable, but easily
“05”, “ddd” would produce “Fri” and “dddd” would produce sortable—handy for log
filenames. Consider using
“Friday” (in US English—other cultures will vary). Table 6 shows UTC though.
each of the custom date and time format specifiers, describing
Table 7. Sample custom date and time format strings and their results
how their meanings change depending on repetition.
Format
Specifier
Meaning Notes and variance by repetition WORKING WITH DATES AND TIMES
d, dd, ddd, Day d 1-31
dddd dd 01-31 The support in .NET for dates and times has changed significantly
ddd Abbreviated day name (e.g. Fri)
dddd Full day name (e.g. Friday)
over time. It’s never simple to do this properly (particularly taking
f, ff ... fffffff Fractions of a f Tenths of a second time zones and internationalization into account, along with all
second ff Hundredths of a second (etc) the normal worries about leap years and other idiosyncrasies) but
The specified precision is always used, with
insignificant zeroes included if necessary
the support has definitely improved. A full discussion of all the
F, FF ... Fractions of a Same as f ... fffffff except insignificant zeroes subtleties is beyond the scope of this reference card, but MSDN
FFFFFFF second are omitted has an excellent page which goes into more depth: http://msdn.
g Period or era For example, “A.D.” microsoft.com/en-us/library/bb384267.aspx.
h, hh Hour in 12 hour h 1-12
format hh 01-12 I suggest you read that article and other resources, but use this
H, HH Hour in 24 hour H 0-23 reference card as a quick aide mémoire.
format HH 00-23
K Time zone offset For example, +01:00; outputs Z for UTC values. DateTime and TimeZone have been in the .NET Framework
m, mm Minute m 0-59 since version 1.0. DateTime simply stores the number of ticks
mm 00-59
since midnight on January 1st, 1 A.D.— where a tick is 100ns.
M ... Month M 1-12
MMMM MM 01-12 This structure was improved in .NET 2.0 to allow more sensible
MMM Abbreviated month name (e.g. Jan)
time zone handling, but it’s still not entirely satisfactory. It’s useful
MMMM Full day name (e.g. January)
s, ss Seconds s 0-59
when you don’t care about time zones, but newer alternatives
ss 00-59 have been introduced. TimeZone is sadly restricted to retrieving
Table 6. Custom date and time format specifiers the time zone of the local machine.
→
much of the time as possible, unless you really need to The System.Text.Encoding class is at the heart of .NET’s encoding
preserve an original time zone. Convert to local dates and functionality. Various classes are derived from it, but you rarely
times for display purposes. need to access them directly. Instead, properties of the Encoding
n If you need to preserve the original time zone instead
class provide instances for various common encodings. Others
(such as ones using Windows code pages) are obtained by calling
of just the offset at a single point in time, keep the relevant
TimeZoneInfo. the relevant Encoding constructor. Table 8 describes the
encodings you’re most likely to come across.
n There are situations where the time zone is irrelevant,
primarily when either just the date or just the time is Name How To Create Description
important. Identify these situations early and make sure UTF-8 Encoding.UTF8 The most common multi-byte representation,
you don’t apply time zone offsets. where ASCII characters are always represented
as single bytes, but other characters can take
n In almost all commonly used formats: more — up to 3 bytes for a character within the
BMP. This is usually the encoding used by .NET
10:00:00.000+05:00 means “the local time is 10am; if you don’t specify one (for instance, when
creating a StreamReader). When in doubt, UTF-8
in UTC it’s 5am” is a good choice of encoding.
10:00:00.000-05:00 means “the local time is 10am; System Encoding.Default This is the default encoding for your operating
default system—which is not the same as it being the
in UTC it’s 3pm” default for .NET APIs! It’s typically a Windows
code page—1252 is the most common value for
DateTimeOffset.Offset is positive if the local time is later
n
Western Europe and the US, for example.
than UTC, and negative if the local time is earlier than UTC. UTF-16 Encoding.Unicode, UTF-16 represents each character in a .NET
In other words, Local = UTC + Offset Encoding. string as 2 bytes, whatever its value. Encoding.
BigEndianUnicode Unicode is little-endian, as opposed to Encoding.
In addition to the types described above, the Calendar and BigEndianUnicode.
DateTimeFormatInfo classes in the System.Globalization ASCII Encoding.ASCII ASCII contains Unicode values 0-127. It does not
include any accented or “special” characters.
namespace are important when parsing or formatting dates
“Extended ASCII” is an ambiguous term usually
and times. However, their involvement is usually reasonably used to describe one of the Windows code pages.
well hidden from developers. Windows Encoding. If you need a Windows code page encod-
code page GetEncoding(page) ing other than the default, use Encoding.
GetEncoding(Int32).
TEXT ENCODINGS ISO-8859-1 Encoding. Windows code page 28591 is also known as
ISO-Latin-1 GetEncod- ISO-Latin-1 or ISO-8859-1, which is reasonably
ing(28591) common outside Windows.
Internationalization (commonly abbreviated to i18n) is
another really thorny topic. Guy Smith-Ferrier’s book, .NET UTF-7 Encoding.UTF7 This is almost solely used in email, and you’re
unlikely to need to use it. I only mention it because
Internationalization (Addison-Wesley Professional, 2006) many people think they’ve got UTF7-encoded text
is probably the definitive guide. However, before you even when it’s actually a different encoding entirely.
consider what resources, localized strings, and so forth, you Table 8. Common text encodings
→
simple to follow these rules. In practice, keeping track of what’s TryEnter Attempts to acquire the monitor, with a timeout
going on can be extremely tricky. Wait Releases the monitor (temporarily) and then blocks until it’s pulsed
Pulse Unblocks a single thread waiting on the monitor
For Windows Forms and WPF:
PulseAll Unblocks all threads waiting on the monitor
Don’t perform any tasks on the UI thread which may take
n
a long time or block. This will result in an unresponsive UI. Table 9. Methods of the System.Threading.Monitor class
changed in more than one thread, you’ll need to synchronize WaitHandle Subclass Description
access, usually with a lock (C#) or SyncLock (VB) statement. A Mutex acts quite like A single thread can acquire the mutex multiple times by
a monitor. waiting on it; the same thread has to release the mutex
Immutable objects can be freely shared between threads. with ReleaseMutex as many times as it has acquired it
n Try to avoid locking for any longer than you have to. Be careful
before any other threads can acquire it. Only the thread
which owns the mutex can release it.
what you call while you own a lock—if the code you call
A Semaphore has a count The initial value of the semaphore is specified in the
acquires any locks as well, you could end up with a deadlock. associated with it. constructor call. When a thread waits on a semaphore, if
the count is greater than zero it is decreased and the call
n Avoid locking on references which other code may try to
completes. If the count is zero, the thread blocks until the
lock on—in particular, avoid locking on this (C#) / Me (VB), count is increased by another thread. The Release method
increases the count, and can be called from any thread.
and instances of Type or String. A private read-only variable
AutoResetEvent and An event is signaled with the Set method. In both cases
created solely for the purpose of locking is usually a good idea. ManualResetEvent wait a thread calling one of the Wait methods will block if the
handles both logically event isn’t signaled. The difference between the two is that
n If you ever need to acquire more than one lock at a time, have a single piece of an AutoResetEvent is reset (to the non-signaled state)
make sure you always acquire those locks in the same order. state: the event is either as soon as a thread has successfully called Wait on it.
signaled or not A ManualResetEvent stays signaled until Reset is called.
Deadlock occurs when one thread owns lock A and tries Physical metaphors can help to remember this behavior.
to acquire lock B, while another thread owns lock B and is AutoResetEvent is like a ticket barrier: when a ticket has
been inserted, the barrier opens but only allows one person
trying to acquire lock A. to go through it. ManualResetEvent is like a gate in a field:
once it’s opened, many people can go through it until it is
n Suspending, interrupting or aborting a thread can leave manually closed again.
your application in a highly unpredictable state unless you
Table 10. WaitHandle subclasses
are extremely careful. These are inappropriate actions in
almost all situations: consult a dedicated threading book More details are available in my threading tutorial at
before using them. http://pobox.com/~skeet/csharp/threads or consult Joe Duffy’s
n When waiting on one thread for something to occur on another, Concurrent Programming on Windows (Addison-Wesley
rather than going round a loop and sleeping each time, use Professional, 2008) for a truly deep dive into this fascinating area.
Monitor.Wait or WaitHandle.WaitOne, and signal the monitor
or handle in the other thread. This is more efficient during the
wait and more responsive when you can proceed. USING C# 3.0 AND VB 9.0 WHEN TARGETING
.NET 2.0 AND 3.0
When using .NET 3.5, prefer ReaderWriter-
Some C# 3.0 and VB 9.0 features can be used freely when
LockSlim over ReaderWriterLock—it performs
FYI better, has simpler characteristics and provides
building a project in VS 2008 which targets .NET 2.0; some
require a bit of extra work; a couple don’t work at all.
fewer opportunities for deadlock.
Fully available features
Automatically implemented properties, implicitly typed local
Monitors and wait handles
variables and arrays, object and collection initializers, anonymous
Monitors are the “native” synchronization primitives in .NET.
There is a monitor logically associated with every object (although types, partial methods, and lambda expressions (converted
the monitor is actually lazily created when it’s first needed). All to delegate instances) can all be used at will. Note that lamdba
members of the System.Threading.Monitor class are static—you expressions are slightly less useful in .NET 2.0 without the Func
pass in an object reference, and it is that object’s monitor which and Action families of delegate types, but these can easily be
is used by the method. declared in your own code to make it “.NET 3.5-ready”.
Using C# 3.0 AND VB 9.0 When Targeting Query expressions themselves are available regardless of framework
version, as they’re only translations into "normal" C# 3.0 and VB
.NET 2.0 and 3.0, continued
9.0. However, they’re not much good unless you’ve got something to
Partially available features—Extension methods and implement, such as Select and Where methods. These are normally
query expressions part of .NET 3.5, but LINQBridge (http://www.albahari.com/nutshell/
Extension methods require an attribute which is normally part linqbridge.html) is an implementation of LINQ to Objects for
.NET 2.0. This allows in-process querying with query expressions.
of .NET 3.5. However, you can define it yourself, at which point
(LINQBridge also contains the ExtensionAttribute mentioned earlier.)
you can write and use extension methods to your heart’s delight.
Just cut and paste the declaration for ExtensionAttribute from Unavailable features—Expression trees and XML literals
http://msdn.microsoft.com/library/System.Runtime. As far as I’m aware, there’s no way to get the compiler to create
expression trees when using .NET 2.0, not least because all the
CompilerServices.ExtensionAttribute.aspx into your own project,
expression tree library classes are part of .NET 3.5. It’s just possible
declaring it in the System.Runtime.CompilerServices namespace.
that there may be a way to reimplement them just as LINQBridge
reimplements LINQ to Objects, but I wouldn’t hold your breath—
In VB you have to have an empty root namespace and it would be much more complicated to do this. As a corollary,
you can’t use "out of process" LINQ without .NET 3.5, as that
Note for this to work—if necessary, create a separate relies on expression trees.
class library project just to hold this attribute. XML literals in VB 9.0 rely on LINQ to XML, which is part of .NET
3.5, so it’s unavailable when targeting .NET 2.0.
DZone, Inc.
1251 NW Maynard
ISBN-13: 978-1-934238-16-5
Cary, NC 27513
ISBN-10: 1-934238-16-3
50795
888.678.0399
DZone communities deliver over 4 million pages each month to 919.678.0300
more than 1.7 million software developers, architects and decision
Refcardz Feedback Welcome
makers. DZone offers something for everyone, including news, refcardz@dzone.com
$7.95
tutorials, cheatsheets, blogs, feature articles, source code and more. Sponsorship Opportunities 9 781934 238165
“DZone is a developer’s dream,” says PC Magazine. sales@dzone.com
Copyright © 2008 DZone, Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, Version 1.0
photocopying, or otherwise, without prior written permission of the publisher. Reference: C# in Depth, Jon Skeet, Manning Publications, April 2008.