0
© { JSL }
1
C#inDetail
Jon Jagger
Software Trainer, Designer, Consultant
www.jaggersoft.com
jon@jaggersoft.com
{ JSL }
Par...
© { JSL }
2
BlatantAdvert
 an interactive, friendly, expert instructor
 Jon has worked for Microsoft using C#
 lots of ...
© { JSL }
3
Agenda  overview
 built-in value types
 enums
 parameters
 control flow
 structs
 constructors
 fields...
© { JSL }
4
C# Programming
Fundamentals
Objects
Relationships
Systems
Overview
© { JSL }
5
C#Features static typing
runtime polymorphism
operator overloading
exceptions
multiple public realization
non ...
© { JSL }
6
HelloUniverse Hiker.cs
using System;
public class Hiker
{
public static void Main()
{
int result;
result = 9 *...
© { JSL }
7
MSIL
C:Sharp>ildasm Hiker.exe
© { JSL }
8
VES  intermediate language, IL
 loading managed code including resolving names
 conversion of IL into nativ...
© { JSL }
9
FortyTwo  C# programs are constructed from tokens
Hiker.cs
/*
*/
using System;
public class Hiker
{
public st...
© { JSL }
10
Tokens  five kinds of tokens in C# programs
token examples
identifiers Hiker Main result
keywords public cla...
© { JSL }
11
Pre-processing  C# has a sensibly limited "preprocessor"
 no #include, no #pragma
 #define, but no macros
...
© { JSL }
12
Identifiers  rules
 made of letters and digits
 must start with a letter
 underscore is a letter
 case s...
© { JSL }
13
Keywords  some identifiers have a fixed meaning
using System;
public class Hiker
{
public static void Main()...
© { JSL }
14
KeywordTable  76 keywords (+ 5 ish)
abstract as base bool break
byte case catch char checked
class const con...
© { JSL }
15
Literals  some tokens represent fixed values
type literal
bool true false
double 3.1415
char 'X'
int 9 6 13 ...
© { JSL }
16
Operators  some tokens represent fixed actions
symbol category
+ - * / % arithmetic
&& || ! logical
< <= > >...
© { JSL }
17
Punctuators  some tokens group or separate
 { and } form scoped blocks
 semi-colons mark the end of a simp...
© { JSL }
18
Declarations  declarations introduce variables into a scope
 a variable has an identifier and a type
 a va...
© { JSL }
19
Expressions  expressions compute things!
 an expression yields a value
 an expression must also have a sid...
© { JSL }
20
TwoTypes  value types
 variables contain their own data directly
 local variables always live on the stack...
© { JSL }
21
C# Programming
Fundamentals
Objects
Relationships
Systems
bool
© { JSL }
22
bool  bool is a keyword
 an alias for System.Boolean
 only values are true and false
bool love = true;
boo...
© { JSL }
23
System.Boolean
namespace System
{
public struct Boolean ...
{
// static fields
public static readonly string ...
© { JSL }
24
boolOperators
int tens = 9 * 6 / 13;
int units = 9 * 6 % 13;
bool isFour = tens == 4;
bool isTwo = units == 2...
© { JSL }
25
boolConversios  no implicit conversions to bool
 ever
 none
 nada
 zip
 under any circumstances whatsoe...
© { JSL }
26
C# Programming
Fundamentals
Objects
Relationships
Systems
byteshortintlong
© { JSL }
27
IntegerTypes
type bits System.
short 16 Int16
int 32 Int32
long 64 Int64
sbyte 8* SByte
ushort 16 Uint16
uint...
© { JSL }
28
System.Int32 namespace System
{
public struct Int32 ...
{
// static fields
public const int MaxValue;
public ...
© { JSL }
29
IntegerLiterals
decimal-integer-literal:
decimal-digits integer-type-suffixopt
decimal-digits:
decimal-digit
...
© { JSL }
30
IntegerOperators
assignment =
in-equality == !=
relational < > <= >=
arithmetic + - * / %
bitwise | & ^ ~
shi...
© { JSL }
31
PrimaryOperators grouping (x)
access x.y
method call f(x)
indexing a[x]
post-increment x++
post-decrement x--...
© { JSL }
32
Precedence primary see previous slide
unary + - ! ~ ++x –-x (T)x
multiplicative * / %
additive + -
shift << >...
© { JSL }
33
Associativity  rule 1
 except for the assignment operators all binary
operators are left-associative
 rule...
© { JSL }
34
EvaluationOrder  operands are evaluated strictly left to right
 same as in Java, unspecified in C++
int m =...
© { JSL }
35
IntegerOverflow  DivideByZeroException, OverflowException
 un/checked expressions
 un/checked { statements...
© { JSL }
36
IntegerMSIL  integer MSIL instructions come in two forms
 one checks for overflow ( eg mul.ovf )
 one does...
© { JSL }
37
IntegerShifting  never throw exceptions
 (u)int shift  count & 0x1F
 (u)long shift  count & 0x3F
int ope...
© { JSL }
38
IntegerConversions  implicit, widening conversions
 never lose information, never throw exception
 explici...
© { JSL }
39
sbyte
short
int
long
sbyte
short
int
long
byte
ushort
uint
ulong
byte
ushort
uint
ulong
signed unsigned
signe...
© { JSL }
40
C# Programming
Fundamentals
Objects
Relationships
Systems
floatdouble
© { JSL }
41
F.P.Types
type
bits
System.
float
32
Single
double
64
Double
CLS
sig. figs 157
yes yes
MSIL float32 float64
±...
© { JSL }
42
System.Double
namespace System
{
public struct Double ...
{
// static fields
public const double Epsilon;
pub...
© { JSL }
43
F.P.Literals real-literal:
digits . digits exponentopt suffixopt
. digits exponentopt suffixopt
digits expone...
© { JSL }
44
F.P.Operators  mostly the same as the integers
 modulus % is permitted (it's not in C++)
 shift operators ...
© { JSL }
45
F.P.Conversions  double  float
 explicit conversion
 never throws
 integer  floating point
 implicit c...
© { JSL }
46
C# Programming
Fundamentals
Objects
Relationships
Systems
decimal
© { JSL }
47
decimalType 
type
bits
System.
decimal
128
Decimal
CLS
sig. figs 28
yes
± 7.9x1028range
suffix M m
float
32
...
© { JSL }
48
System.Decimal namespace System
{
public struct Decimal ...
{
// static fields
public static readonly decimal...
© { JSL }
49
moreConversions  float / double  decimal
 explicit conversion (FP have greater range)
 always checked, ma...
© { JSL }
50
C# Programming
Fundamentals
Objects
Relationships
Systems
char
© { JSL }
51
charType
type
bits
System.
char
16
Char
CLS yes
0x0000
0xFFFF
min
max
Unicode 3.0
You idiot, that's a chair
© { JSL }
52
System.Char
namespace System
{
public struct Char ...
{
// static fields
public const char MaxValue;
public c...
© { JSL }
53
charLiterals character-literal:
' character '
character:
single-character
simple-escape-character
hex-escape-...
© { JSL }
54
charConversions  char is classified as an integral type
 you can do char arithmetic
 implicit conversion f...
© { JSL }
55
C# Programming
Fundamentals
Objects
Relationships
Systems
enum
© { JSL }
56
enumDeclaration  a user-declared value-type
enum Suit
{
Clubs, Diamonds, Hearts, Spades
};
class Example
{
s...
© { JSL }
57
enumNotes
enum Suit : int
{
Clubs,
Diamonds,
Hearts = 42,
Spades,
}
the underlying integer type
can be any of...
© { JSL }
58
enumUse  enums implicitly derive from System.Enum
Suit trumps = Suit.Club;
string[] names = System.Enum.GetN...
© { JSL }
59
enumOperators  enum variables can mostly be used as ints
assignment =
in-equality == !=
relational < > <= >=...
© { JSL }
60
enumConversions  implicit conversion
 literal 0 to any enum type
 explicit conversions
 from enum to enum...
© { JSL }
61
Terminology  two kinds of value type
 enum types
 struct types
 two kinds of struct types
 user-defined ...
© { JSL }
62
C# Programming
Fundamentals
Objects
Relationships
Systems
Parameters
© { JSL }
63
CopyParameters  a plain parameter is a copy of the argument
 no frills bitwise copy
 the argument must be ...
© { JSL }
64
refParameters  a ref parameter is an alias for the argument
 no copy takes place
 argument must be definit...
© { JSL }
65
outParameters  an out parameter is an alias for the argument
 no copy takes places
 argument need not be d...
© { JSL }
66
inParameters?  readonly, const and in, are all C# keywords
 they cannot be applied to parameters
 ref / ou...
© { JSL }
67
ParameterNotes  sdclass Notes
{
... Good( int copy) ...
... Error(ref int alias) ...
... Error(out int alias...
© { JSL }
68
MoreNotes
class Notes
{
int Error() { ... }
double Error() { ... }
}
return type is not
part of signature
int...
© { JSL }
69
C# Programming
Fundamentals
Objects
Relationships
Systems
ControlFlow
© { JSL }
70
Blocks  a block and its parent block
 cannot have a variable with the same name
 sibling blocks
 can have...
© { JSL }
71
if  no built-in conversions to/from bool
 System.Convert.ToBoolean(int i) exists though
 definite assignme...
© { JSL }
72
switch  usual syntax
 switch on integral types
 case labels must be compile time constants
 etc
switch (t...
© { JSL }
73
caseNotes  unusual syntax
 you can switch on a string
 fall through is illegal, even on default clause
 y...
© { JSL }
74
while/do  standard Java,C++ like syntax
int m = 0;
while (m != 10)
{
Console.Write("{0} ", m);
m++;
}
int m ...
© { JSL }
75
for  for statement
 declared variables are scoped to for statement
for (int m = 0; m != 10; m++)
{
Console....
© { JSL }
76
foreach  from shell, VB, PERL, etc
 works on any collection, including [ ] arrays
using System.Collections;...
© { JSL }
77
foreachNotes  foreach ( type identifier in expression )
 type and identifier declare an iteration variable
...
© { JSL }
78
continue/break  no labelled break statement
int m = 0;
for (;;)
{
Console.Write("{0} ", m);
m++;
if (m != 10...
© { JSL }
79
C# Programming
Fundamentals
Objects
Relationships
Systems
struct
© { JSL }
80
structDeclaration  a user-defined value-type
struct Pair
{
public int X, Y;
};
optional semi-colon
by conven...
© { JSL }
81
structCreation  a struct local variable lives on the stack
 is not definitely assigned, just like int
 can...
© { JSL }
82
structUse  usual dot operator to access field
 field must be assigned before its value is used
 default c'...
© { JSL }
83
structConstructor  unusual rules
 compiler declares default c'tor
 you cannot declare the default c'tor
 ...
© { JSL }
84
:this(...)  a c'tor can call a sibling c'tor
 syntax is similar to C++
 no general member-init-list syntax...
© { JSL }
85
instanceFields  instance fields...
 are default initialised in compilers default c'tor
 must be explicitly...
© { JSL }
86
readonlyFields  readonly instance fields...
 are instance fields that cannot be assigned to
compile time er...
© { JSL }
87
constFields  const fields are implicitly static
 only simple types, enums, & string can be const
 const fi...
© { JSL }
88
staticFields  to declare static fields of other types
 use static keyword!
 static fields are default init...
© { JSL }
89
LocalVariables  local variables can be declared const
 but not static, and not readonly
 and const is only...
© { JSL }
90
staticConstructor  a static c'tor initialises the type
 can initialize static fields but not const fields
...
© { JSL }
91
CopyConstructor?  you can declare a "copy constructor"
 it is not called for value parameters/returns
 a c...
© { JSL }
92
CopyAssignment?  you cannot overload simple assignment
 a copy is always a plain bitwise copy
struct Pair
{...
© { JSL }
93
C# Programming
Fundamentals
Objects
Relationships
Systems
Operators
© { JSL }
94
Overloading  you can
 overload most operators
 you can't
 create new operators
 change the multiplicity ...
© { JSL }
95
operatorSyntax  operators are always defined as
 public static methods (never virtual)
 copy parameters on...
© { JSL }
96
Assignment  you can't overload assignment, but this...
X op= Y
X = X op Y
is processed as this...
except tha...
© { JSL }
97
++--  you can overload ++ and --
 a single operator supports prefix and postfix
 prefix returns the result...
© { JSL }
98
operatorFamilies  some operators have natural partners
 you can't have one without the other
struct Meter
{...
© { JSL }
99
operatortrue/false  designed for tri-state boolean types
 eg SQL types: true, false, Null
 also have the e...
© { JSL }
100
Conversions  must be public and static
 must be implicit or explicit
 implicit : compiler can call, shoul...
© { JSL }
101
Example  "readonly" local variable
struct ConstInt
{
public ConstInt(int value)
{
this.value = value;
}
pub...
© { JSL }
102
ConversionNotes  implicit conversion resolution
 optional standard implicit conversion
 user defined impl...
© { JSL }
103
C# Programming
Fundamentals
Objects
Relationships
Systems
Indexers
© { JSL }
104
[]  indexers provide [ ] like syntax of use
 always an instance member, can be virtual
 no ref-out parame...
© { JSL }
105
getandset  indexers can only contain accessors
 get { accessor } for read context
 set { accessor } for w...
© { JSL }
106
getorset  an indexer with no set accessor
 is a read-only indexer
 and indexer with no get accessor
 is ...
© { JSL }
107
IndexerNotes  indexers compared to arrays
 indexers can use multiple parameters
 indexers can use non int...
© { JSL }
108
C# Programming
Fundamentals
Objects
Relationships
Systems
Properties
© { JSL }
109
getandsetAgain  an object oriented smart field
 get and set accessors
 instance property can be virtual
s...
© { JSL }
110
staticProperties  properties can be static
 unlike indexers
class Console
{
...
public static readonly Tex...
© { JSL }
111
PropertyNotes  properties
 are not lvalues, can't be ref-out args
 can't be void
 can't take arbitrary p...
© { JSL }
112
Summary  .NET, IL, CLS, CLR, VES
 stack values – enum, struct (eg int )
 control flow – switch, foreach
...
Upcoming SlideShare
Loading in...5
×

Csharp In Detail Part1

4,226

Published on

Published in: Business, Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,226
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
358
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide
  • ACCU Spring Conference, Christ Church College, Oxford, Friday 30th March 2001.

    { JSL }
    Jagger Software Limited http://www.jaggersoft.com Tel. +44 (0) 1823 354 192
    Hi, I'm Jon Jagger, a freelance software trainer, designer, and consultant. I specialise in curly bracket languages, hence { JSL }. In a former life I was QA Training's C++ and C product consultant. I'm an UK C++ standards panel member and a regular contributor to the ACCU Overload journal. I'm married with three increasingly larger children. My interests include training excellence, design, problem solving, and monty python (which should be required knowledge for all software developers). Forget the technical interview, just recite the parrot sketch. I don't really know what else to say in a short bio such as this. I'm very very good at sleeping. And breathing. Both of which I practice a lot.
  • ACCU Spring Conference, Christ Church College, Oxford, Friday 30th March 2001.

    { JSL }
    Jagger Software Limited http://www.jaggersoft.com Tel. +44 (0) 1823 354 192
    Hi, I'm Jon Jagger, a freelance software trainer, designer, and consultant. I specialise in curly bracket languages, hence { JSL }. In a former life I was QA Training's C++ and C product consultant. I'm an UK C++ standards panel member and a regular contributor to the ACCU Overload journal. I'm married with three increasingly larger children. My interests include training excellence, design, problem solving, and monty python (which should be required knowledge for all software developers). Forget the technical interview, just recite the parrot sketch. I don't really know what else to say in a short bio such as this. I'm very very good at sleeping. And breathing. Both of which I practice a lot.
  • ACCU Spring Conference, Christ Church College, Oxford, Friday 30th March 2001.

    { JSL }
    Jagger Software Limited http://www.jaggersoft.com Tel. +44 (0) 1823 354 192
    Hi, I'm Jon Jagger, a freelance software trainer, designer, and consultant. I specialise in curly bracket languages, hence { JSL }. In a former life I was QA Training's C++ and C product consultant. I'm an UK C++ standards panel member and a regular contributor to the ACCU Overload journal. I'm married with three increasingly larger children. My interests include training excellence, design, problem solving, and monty python (which should be required knowledge for all software developers). Forget the technical interview, just recite the parrot sketch. I don't really know what else to say in a short bio such as this. I'm very very good at sleeping. And breathing. Both of which I practice a lot.
  • Static typing, runtime polymorphism (virtual methods), exceptions and "reference" types, are features also found in C#, C++ and Java.
    Value types, and operator overloading are features found in C#, C++ but not in Java. Compile time polymorphism (templates, aka generics) is promised for a later release of C#.
    A virtual execution system (similar to the Java VM), Object as the super base class of all types, single public inheritance (extension in Java), multiple public realization (implements in Java), non determinstic finalization, garbage collection, multithreading, and reflection are features found in C# and Java but not in C++.
    C# has a truly unified type system (achieved through boxing and unboxing, covered later). C++ does not. Java almost has a unified type system (primitive value types need to be manually wrapped).
  • Unlike in Java the name of the C# source file does not have to correspond to the name of the public class contained in that source file.
    C# is a case sensitive language. Main is spelled with a capital M.
    There are several Main variations borrowed from C++ and Java. You can declare Main to return an int, with a return value of zero indicating success:
    public static int Main() { ... return 0; }
    You can declare Main as a void function:
    public static void Main() { ... }
    You can also declare Main to accept an array of strings:
    pubic static void Main(string[] args)
    {
    for (int i = 0; i != args.Length; i++) {
    System.Console.WriteLine(args[i]);
    }
    }
    The program's Main must be a static method. If there is more than one public static Main in a program one of them must be designated the entry point to the program using the /main:<type> command line option (where type is the name of the struct/class containing the selected Main).
  • Microsofts IL (Intermediate Language) is an important parts of the .NET VES (virtual execution system). The virtual execution model consists of an evaluation stack used for pushing arguments to methods and built-in operations. At a method call the arguments (possibly including this) are transferred from the control of the calling method to the control of the called method. Returned values of any instantiable type are pushed on the stack before method return.
    The IL instruction set can be divided into the following categories of instructions:
  • The important parts of the .NET VES (virtual execution system) are:
  • The purpose of this slide (written by a programmer with a soft Irish accent) is to present a code fragment that is dissected in the following slides.
  • The C# grammar distinguishes between a number of different tokens: identifiers, keywords, literals, operators and punctuators. Note that while C# does have a C/C++ like preprocessor, the #define directive is strictly limited to defining a simple token and cannot define a replacement set of tokens. This effectively means that preprocessing tokens do not exist. Which is nice.
    When generics (templates) are added to C# it is likely they will use the < > notation familiar to C++ programmers. It is also likely that C# will create a special exception to the maximal-much rule allowing >> to be parsed in context:
    int x = 42 >> 4; // bitshift
    wibble<wibble<int>> variable; // declaration
  • C# has a limited #define directive. You can use it to specify that the named pp-token is defined. You cannot #define true or false (this is because they can be used as bool literals inside a pp-expression). You can also use #undef to specify that the named pp-token is no longer defined. It is not an error if the specified pp-token is not already defined. There are no function macros, so both these are errors:
    #define MACRO(exp) do exp; while(0)
    #define MACRO(exp)
    #defined pp-tokens are only useful as part of the expression used to select or skip sections of code (skipped sections do not have to be syntactically well formed).
    #if TESTED && INSPECTED
    ...
    #endif
    The #line directive is useful for tools that generate C# code. There are no built-in __FILE__ or __LINE__ tokens in C#.
    The #error and #warning directives both emit a supplied pp-message diagnostic. A #error is fatal and halts the build, a #warning is non-fatal and does not halt the build.
    The #region and #endregion directives are used in pairs and can be nested. They have no declarative meaning. The editor in Visual Studio 7 uses them to create a folding editor.
  • The SDK guidelines recommend that public identifiers start with an uppercase letter using the PascalCase convertion and that private identifiers start with a lowercase letter using the camelCase convention. For example:

    class Point
    {
    ...
    public int X() { return x; }
    public int Y() { return y; }
    private int x, y;
    }

    In C# an identifier in a derived class can completely hide an identifier in a base class. Because of this you are strongly advised to follow this guideline.
    Note also that a CLS compliant program must not use public identifiers that differ only in case. For example:
    [CLSCompliant(true)] // attribute
    ...
    public void Name() {...}
    public void name() {...} // error CS3005
  • The keywords in the above slide are coloured in blue. For those of you reading this in monochrome the keywords are using, public, class, static, void, int.
    Keywords have a fixed meaning. Part of learning a new language is learning the meaning of the keywords. Another more exciting part is learning how to create larger syntactic elements once the basic syntax has been grasped. But you have to start at the beginning. The time and effort expended learning the keywords and their meanings is well spent, especially as the keywords are fixed; they will not change (unlike just about everything else in computing!).
  • In Beta 1 there are 76 keywords that have a fixed meaning in all contexts. There are also a few 2nd-class keywords that have a fixed meaning only in certain special contexts. For example, value can be used as the name of a local variable almost everywhere. In one context (the set accessor of a property) value is effectively a keyword.
    You are allowed to use @ before a keyword to create a legal identifier.
    For example:
    int @int = 42;
    This is not recommended and is presumably included for the benefit of code generation tools.
    You can also use the @ symbol to create verbatim-string literals that span many lines. This is useful when creating regular expressions for use with the Regex class. For example:
    string pattern = @"
    ( # start the group
    abra(cad)? # match abra and optional cad
    )+"; # one or more occurences
  • Only the built-in types have literal syntax. There is no way to create literals for user-defined structs or classes.
    Literals are pure values. They are constants. They cannot be modified.
    6++; // compile time error
    Just like in Java, a C# string literal is a constant immutable value of type string.
  • C# has a rich set of operators making it a very expressive langauge. All the operators in the table above are present in C#, C++, and Java. In C# all the above operators (except simple assignment) can be overloaded for user defined structs and classes. This is not possible in Java.
  • A C# class/struct/enum definition does not require a terminating semi-colon (like Java).
    public class Hiker
    {
    ...
    } // no ; OK
    However, as a concession to C++ programmers, a semi-colon may be used and has no affect on the meaning of the program:
    public class Hiker
    {
    ...
    }; // also OK
    In Java a function declaration can have a trailing semi-colon. In C++ it cannot (but many compilers allow it). In C# it is not allowed and causes a compile time error:
    public class Hiker
    {
    public void Hitch() { ... }; // ; not OK
    }
  • It is illegal to declare a variable in a context where that variable would be unusable. For example:
    if (...)
    int x = 42; // compile-time error
    else
    ...
    Declarations and expressions can be freely mixed. Most modern C++/Java style guidelines recommend delaying the declaration of a variable to increase the chance of being able to initialize it. This is important because C#, like Java, will not allow the value of a not-definitely assigned variable to be used.
    There are no pointers or typedefs in C#. Hence troublesome C++ declarations, such as:
    int *ptr, value; // C/C++
    are no longer an issue. A useful style is to declare multiple variables in the same declaration when the variables are necessarily of the same type:
    int x, y;
  • A C# expression statement must have an affect on the program state. This means that only assignment, call, increment, decrement, and new expressions can be used as a statement (this is true for built in types and user-defined types):
    42; // compile-time error
    42 == 42; // compile-time error
    However, initialising a variable in a C# declaration statement is deemed a side effect: Hence the following are legal and at best generate a warning:
    { int m = 42; }
    { bool b = 42 == 42; }
  • You may be looking at this slide and wondering where the built-in types such as int and double are. The answer is that in C# the built-in value types are structs in disguise called simple types. The main difference between simple struct types and user-defined struct types is that the former have a literal syntax (such as 42 which is an int) whereas the latter do not.
    There is also a third type category: pointers, but pointers can only be used in C# code declared as unsafe.
  • The first code box declares and intializes two bool variables called love and teeth.
    The second code box is identical to the first code box. System.Boolean is an alias for bool. They are synonyms.
    The third code box also uses the identifier Boolean as a synonym for bool. It does this using the shorthand notation of dropping the System. prefix which the compiler implicitly adds back in due to the using System; directive.
    The code in the third box generates an error. There is no global type called Boolean and there is no using System; directive so the compiler cannot resolve Boolean as the name of a type.
  • System.Boolean is a struct that lives inside the System namespace. It realizes a number of interfaces (structs and inheritance are fully covered later):
    public struct Boolean : IComparable, IConvertible
    {
    ...
    }

    The value of System.Boolean.FalseString is "False" with a captial F.
    The value of System.Boolean.TrueString is "True" with a capital T.

    Instance methods of System.Boolean can be called directly on bool literals:
    true.ToString();
    Static methods of System.Boolean can be called using bool as an alias for System.Boolean:
    bool.Parse(Console.ReadLine());
  • Signed numbers and byte are in the Common Language Specification (CLS). ushort, uint, and ulong are not in CLS. The types that are part of the CLS form an integral [sic] part of the CTS (common type system) are are supported directly by the VES (virtual execution system).
    Note: a CLS compliant program cannot expose unsigned types in the public interface of a struct/interface/class but a CLS compliant program can use unsigned types in the private parts of a struct/class.
    The bitsizes of each type are precisely specified just like in Java (and unlike in C++).
    In code you can use the raw keyword type name (eg int) or its equivalent alias (eg System.Int32). There is no difference (except in runtime reflection when you have to use the string "System.Int32" rather than the string "int"). The guideline is to prefer the keyword.
    Note that a byte in C# is an unsigned 8 bit integer whereas in Java a byte is a signed 8 bit integer.
    The names of these 8 integral types in IL are intN (where N is the number of bits) for the signed types and unsigned intN, for the unsigned types.
    The byte and sbyte bit sizes are marked with an asterisk. This is because the minimum size of an array element is 16 bits (2 bytes).
  • System.Int32 is a struct that lives inside the System namespace. It realizes a number of interfaces (structs and inheritance are fully covered later):
    public struct Int32
    : IComparable, IFormattable, IConvertible
    {
    ...
    }
    IFormattable is an interface that allows user-defined types to define their own format strings (in exactly the same whay that printf doesn't).
    The value of System.Int32.MinValue is unchecked ((int)0x80000000), that is, -2,147,483,648, == -(2^32)
    The value of System.Int32.MaxValue is 0x7FFFFFFF, that is, +2,147,483,647, == 2^32 – 1
    int is a synonym for System.Int32. They can be used completely interchangeably.
  • The syntax for integer literals is the same in C# as it is in C++ and Java except for two minor differences: firstly, C# does not support octal integer literals; C++ and Java do. Secondly, C# supports unsigned integer literals (via the Uu suffix); Java does not.
    The keyword int is an alias for the System.Int32 struct. In C# int is classified as a simple-type and differs from other user-defined structs in a number of ways:
    Most simple types have a syntax for creating literal values. For example 42 is a literal of type int, 23.11 is a literal of type double. C# offers no facility for creating literals of user-defined struct (or class) types. The values of user-defined structs (or classes) are usually created through constructors.
    When the operands of an expression are all simple-type literals, the compiler can evaluate the expression as a compile-time expression. When the operands of an expression involve user-defined struct values, the expression will always be a runtime-expression.
    You can declare immutable variables of simple types using the const keyword. You cannot declare immutable variables of user-defined structs (or classes) using the const keyword.
    As a matter of style, the C# language specification recommends using L instead of l when writing literals of type long since it is easy to confuse the letter l with the digit 1. In fact using lowercase l generates a warning. Why didn't they just enforce the use of uppercase suffixes?
  • C# defines the usual range of integer operators.
  • These are the primary C# operators which all share the highest precedence.
    The increment and decrement operators are overloadable for custom types.
    The pointer member access operator -> can only be used in unsafe (unmanaged) code.
    Strictly speaking an indexer is not considered an operator (there are some language rules this affects). Indexers can be defined for custom types.
    new is only ever used in conjunction with calling a constructor and is not overloadable. Using new to call a struct constructor allocates memory from the stack (honest) whereas using new to call a class constructor allocates memory from the heap. In C# structs are value types whereas classes are reference types.
    sizeof returns the size of a type or expression and can only be used in code marked as unsafe.
    checked and unchecked are used to control detection of integer arithmetic overflow (covered shortly).
  • All the unary operators can be overloaded for user-defined types. The type cast operator can be overloaded by creating implicit or explicit conversion operators.
    The multiplicative, additive, shift, relational (except for is and as), equality, and bitwise operators can also be overload for user-defined types.
    The && and || can sort of be overloaded by using true/false conversion operators (which retain the short-circuiting behaviour). Very strange.
    The conditional (?:) and the assignment operators cannot be overloaded. However, a compound assignment is effected in terms of its underlying operator which can be overloaded.
    This precedence table is essentially identical to that of C++ except that C++ has more operators. It is instructive to note the C++ operators that do not appear in the above table:
  • The associativity rules in C# are the same as in C++ and Java (which in turn were chosen for compatibility with C). Most expressions can be written naturally without parentheses. However, there are a few common idioms which require parentheses. For example:
    //class cast combined with member access
    ((System.Int32)boxed).Int32();
    // assignment combined with comparison
    while ((line = src.ReadLine()) != null) { ... }
  • By default compile time integer expressions generate an OverflowException and runtime integer expressions silently overflow. However this default behaviour is configurable. There is a command line option /checked+ to turn on overflow checking and similarly /checked- to turn off overflow checking.
    When overflow checking is on an expression that would normally silently wrap throws an OverflowException. You can also use the checked/unchecked operators to control overflow checking: checked expressions/statements are always checked, unchecked expressions/statements are never checked.
    A checked ( expression ) checks a single expression. It can be used on any expression but only affects the integer operators that can cause overflow: unary { ++, --, - }, binary { + - * / }, and explicit conversion operators between integral types. A checked expression is an expression; it has an outcome that can be used as part of a larger expression:
    int outcome = checked( ... );
    A checked { statement } checks a sequence of statements. A checked statement does not have an outcome; it is not an expression.
    int outcome = checked { ... }; // compile-time error
    The checked and unchecked operators only affect the overflow checking context of the operations they "textually" contain. They have no effect on textually contained function member invocations.
    Division by zero always throws a DivideByZeroException.
  • If the left hand operand is int or uint (32 bit types) the shift distance is always in the range 0 to 31 inclusive. Only the five lowest-order bits of the right hand operand are used as the shift distance.
    n << s  n << (s & 0x1F)
    If the left hand operand is long or ulong (64 bit types) the shift distance is always in the range 0 to 63 inclusive. Only the six lowest-order bits of the right hand operand are used as the shift distance.
    n << s  n << (s & 0x3F)
    The integer shift operators never throw exceptions. You can overload the shift operators for user-defined structs/classes. There is no >>> operator as in Java, since C# has signed and unsigned types, (although the unsigned types are not part of the Common Language Specification CLS).
    There are no shift operators for shifting bytes or shorts. Shifting a byte/short will cause the byte/short to be converted to an int. This means the return type will be an int. This means, given b is a byte, the following will not compile:
    b = b << 1; // can't assign an int to a byte
    To solve this problem you can use an explicit conversion (a cast) or use the compound assignment form of the shift operator:
    b = (byte)(b << 1);
    b <<= 1;
  • Integer to integer conversions are performed using explicit conversion operators (in other words; casts). Casts can be used in a checked expression:
    int m = int.Parse(Console.ReadLine());
    short s;
    s = checked((short)m); // 1
    s = unchecked((short)m); // 2
    s = (short)m; // 3
    Statement 1 is always checked and if the value of m is outside the range of a short an OverflowException is throw.
    Statememt 2 is never checked and never causes an exception to be thrown.
    Statement 3 may or may not be checked (depending on the optional use of the /checked+ compilation flag).
    The top left table in the slide is the same in Java (except in Java the unsigned 8 bit integer is called byte and not sbyte)

  • C# supports two floating point types: float and double. There is no long double as in C/C++. Both types conform the the IEEE 754 formats:









    In C#, C++, and Java the suffix for float is F or f. In C#, as in Java, the suffix for double is D or d. In C++ there is no explicit suffix for doubles other than L or l for the long double type (which does not exist in C# or Java).
    As well as System.Single and System.Double there are other varieties of cream classes in the System namespace: Whipping, Pouring, Clotted, and Ice to name but four.
    More information on IEEE-754 can be found at: http://www.ieee.org
  • The keyword float is an alias for the System.Single struct type and the keyword double is an alias for the System.Double struct type. This means that when you write:
    double d;
    you are actually writing:
    System.Double d;
    If you use a using directive to make all types from the System namespace available you do not need to explicitly name the System prefix:
    using System;
    ...
    double d1;
    Double d2;
    There are a few typename keywords that share this property of only differing in the first letter: object  System.Object, string  System.String. You are recommended to use the keyword typename.
  • The M or m suffix is used for decimal literals (covered shortly).
    The literal 234F (which does not contain a decimal point) is legal in C# and in Java but not in C or C++. Similarly the literal 234.F (which does contain a decimal point) is not legal in C# but is legal in C, C++, and Java.
    The fact that 234.F is not legal C# is due to potential grammatical ambiguities. Consider; 234 is a literal of type int and int which is an alias for System.Int32 which is a struct that declares fields and methods. Suppose System.Int32 declared an instance field called F. The syntax 234.F would then be ambiguous: is it a double literal with a type suffix or the F field being accessed through an int value? The compiler thinks the latter:
    float f = 123.F; // compile time error. No F in 'int'
    string s = 123..ToString(); // compile time error
    Note however that the following are legal:
    double d = 123.0D;
    string s = 123.0.ToString();
    There appears to be no way in C# to initialise a floating point literal other than in decimal radix (in Java you can convert a IEEE bit pattern contained in a long into a double using the Double.longBitsToDouble method.
  • You can use the % operator on floating point operands (you can in Java too, but not in C++). You cannot use the shift operators on floating point operands (you can't in Java or C++ either).
    Floating point operators never throw exceptions (this includes the assignment operator – remember the definite assignment rule). Instead in exceptional [sic] circumstances floating point operations produce zero, infinity, or NaN, as described below:
  • Converting a double to a float requires a cast. The double value is first rounded to the nearest float value. If the double value is too small to represent as a float, the result becomes positive zero or negative zero. If the double value is too large to represent as a float, the result becomes positive infinity or negative infinity. If the double value is NaN the result is also NaN.
    An integer to floating point conversion is always implicit and never requires a cast (although one may be used if desired). Conversions from int, uint, or long to float and from long to double may cause a loss of precision, but will never cause a loss of magnitude. The other implicit integer to floating point conversions never lose any information.
    Conversion from a float or double to an integer type require an explicit cast. The source value is rounded to the nearest integral value, and this integral value becomes the result of the conversion. If the resulting integral value is outside the range of the destination type, an OverflowException is thrown. At least, that is the documented behaviour in the language specification. As at Beta 2 whether an OverflowException is actually thrown depends on the overflow checking context:
    double d = double.Parse(Console.ReadLine());
    int m;
    m = checked((int)d); // 1 may throw
    m = unchecked((int)d); // 2 never throws
    m = (int)d; // 3 depends on context
  • The C# language specification states that "The decimal type is a 128-bit data type suitable for financial calculations". A decimal is represented as a 96-bit integer scaled by a power of ten.
    The decimal type holds 28 digits and the position of the decimal point in those digits. The decimal type is useful for financial calculations; it has high precision and can store base 10 numbers (as you might imagine for a type called decimal!) The number 0.1 is stored exactly in a decimal but inexactly as a recurring binary in a floating point type (float or double).
    The floating-point suffix for the decimal type is M or m (m for money?).
    decimal value = 3552566.23M;
    The decimal type is 128 bits, and since a C# byte is always 8 bits long, decimal is 16 bytes long (despsite what every other C# book says!)
  • The decimal keyword is an alias for System.Decimal, a struct that lives inside the System namespace. It realizes a number of interfaces (structs and inheritance are fully covered later):
    public struct Decimal
    : IConvertible, IComparable, IFormattable
    {
    ...
    }

    sizeof(decimal) is classified as a value and not a constant. This is despite the fact that the C# language specification clearly states that decimal is a 128 bit type.
  • When converting a float or double to a decimal, the source value is converted into a decimal representation and rounded to the nearest number after the 28th decimal place if required. If the source value is too small to represent as a decimal, the result becomes zero. If the source is NaN, infinity, or too large to represent as a decimal, an InvalidCastException is thrown.
    When converting a decimal to a float or double, the decimal value is rounded to the nearest float or double value. This conversion may lose precision (since the decimal type has greater precision) but never throws an exception.
    When convering a decimal to an integral value, the source value is rounded towards zero to the nearest integral value, and this value becomes the result of the conversion. If the resulting integral value is outside the range of the destination type an OverflowException is thrown.
    An integral to decimal conversion is an implicit conversion because the decimal type can represent every possible integer value.
    There is no concept of +0, -0, +infinity, -infinity, or NaN for the decimal type.
    Note that the double to decimal conversion is not implicit. This means that you cannot initialize or assign a decimal from an unadorned floating-point literal:
    decimal failure = 3552566.23; // compile time error
    decimal success = 3552566.23M; // OK
  • The char type represents an unsigned 16-bit integer with values between 0 and 65535. The set of possible values for the char type corresponds to the Unicode character set.

    Unicode consortium. The Unicode Standard, Version 3.0. Addison Wesley, Reading, Massachusetts, 2000. ISBN 0-201-616335-5
  • System.Char is a struct that lives inside the System namespace. It realizes a number of interfaces (structs and inheritance are fully covered later):
    public struct Char
    : IComparable, IConvertible
    {
    ...
    }
  • A new-line terminal is defined as: a carriage return character (U+000D), a line feed character (U+000A), a carriage return character (U+000D) followed by line feed character (U+000A), a line separator character (U+2028), or a paragraph separator character (U+2029).
    In C# (as in Java) a character literal contains the representation of a single character (not true in C++!).
    A character that follows a backslash character must be one of the designated characters otherwise a compile time error occurs.
  • There are no implicit conversions from other types to the char type. In particular, even though the sbyte, byte, and short types have ranges that are fully representable using the char type, implicit conversions from sbyte, byte, or short to char do not exist.
    char exists mainly to be the element type of string.
  • An enum declaration may appear in the same places as a class declaration.
    An enum declaration defines the name, accessibility, underlying type, and members of the enum. The underlying type must be able to hold all the values of the named constants defined in the enum.
    The named constants defined in the enum are scoped inside the enum. In other words the following is not well-formed:
    Suit trumps = Clubs; // compile time error
    Clubs must be scoped as a member of Suit:
    Suit trumps = Suit.Clubs; // OK
    Java does not have enums (not to be confused with Enumeration which is an interface). In Java enums have to be faked up using static readonly fields:
    class Suit
    {
    public static readonly Club = ...;
    }
    C++ does have enums but the named constants do not require the name of the enum as a prefix.
    enum suit { clubs, diamonds, hearts, spades };
    suit trumps = clubs; // OK in C++
  • Uniquely, a C# an enum type may explicitly declare its underlying type as sbyte, byte, short, ushort, int, uint, long, or ulong. An enum declaration that does not explicitly declare its underlying type defaults to an implicit underlying type of int.
    Named constants have the same type as the underlying type and must have a value in the range of the underlying type (for example, you cannot create a named constant with a negative value if the underlying type is explicitly declared as uint). If the named constant is not given an explicit constant value it defaults to the value of the previous named constant plus one (and the default value of the first named constant is zero). It is not an error for more than one named constant in the same enum declaration to have the same value. The initializer for a named constant cannot include itself either directly or indirectly and cannot refer to a following named constant (this would create a circular dependency and is one of the few cases of an order dependency in C#).
    The last named constant can be declared with a trailing comma. This makes it easy to add more named constants in the future, although if this is likely you should consider not using an enum! An enum is best suited to a fixed number of grouped names: you are extremely unlikely to need a fifth suit, or a thirteenth month, etc. Try and avoid explicitly initializing named constants.
    Enum members (such as Club) implicitly have public declared accessibility.
    As a gesture to C++ programmers, an enum declaration is allowed an optional trailing semi-colon (it is in Java too). It's best to get out of the habit using a trailing semi-colon as it not perimtted on a function definition (it is in Java).
  • System.Enum is a class that lives inside the System namespace. It realizes a number of interfaces (classes and inheritance are fully covered later): public class Enum
    : IComparable, IFormattable, IConvertible
    { ... }
    enum types (such as Suit) implicitly derive from System.Enum (as well as implicitly or explicitly deriving from their underlying type). Note that this is different to types as the System.Int32 struct which is an alias for int.
    C# has powerful introspection capabilities (introspection is the ability of a program to observe and reason about its own state). Unlike C++, C# can easily print out the name of a enum variable. You can do this via the IFormattable interface: directly by calling the Format method or indirectly by using the "{0}" format string. Note that using the ToString method prints the value of the enum variable and not its name.
    System.Enum is a special class designed to be used only as an implicit base class of all enum types.
    you cannot explicit derive from System.Enum yourself (error CS0644)
    you cannot create an instance of System.Enum (constructor is protected)
    However, you can declare a (reference) variable of type System.Enum
  • if value does not correspond to a named constant Format prints the value.
  • ValueType is a class that lives in the System namespace. This class the root class of all value types (and implicitly derives from the System.Object class). Via a little introspection you can prove that the value types derive from System.ValueType, and that arrays and classes do not.
    int m = 42;
    Suit trumps = Suit.Club; // Suit is an enum
    Pair p = new Pair(); // Pair is a struct
    int[] array = new int[42];
    ValueType v = new ValueType();
    Console.WriteLine(m.GetType().BaseType);
    Console.WriteLine(trumps.GetType().BaseType);
    Console.WriteLine(p.GetType().BaseType);
    Console.WriteLine(array.GetType().BaseType);
    Console.WriteLine(v.GetType().BaseType);
    The five WriteLine statements print System.ValueType (three times), then System.Array, and then System.Object.
  • A parameter declared without a ref or out modifier is a value parameter. A value parameter only comes into existence upon invocation of the function member to which the parameter belongs, and is initialized with the value of the argument given in the invocation. A value parameter ceases to exist when the flow of control leaves the function member (either via normal return or a thrown exception).
    For the purposes of definite assignment checking, a value parameter is considered initially assigned. That is, once the invocation takes place the value parameter is considered definitely assigned. However, only a definitely assigned argument can be passed as a value parameter.
    int m; // m not definitely assigned
    Func(m); // compile time error
    The argument corresponding to a value parameter can be a pure value and need not be a named variable:
    Func(42);
    Func(Suit.Club);
    Func(new Pair());
  • A parameter declared with a ref modifier is a reference parameter. A reference parameter does not create a new storage location. Instead the reference parameter is an alias for the variable given as the argument in the function member invocation. In effect a reference parameter is another name for an existing variable.
    Note that the ref modifier is required on both the function member declaration and on the function member invocation.
    For the purposes of definite assignment checking, a reference parameter is considered initially assigned. That is, once the invocation takes place the reference parameter is considered definitely assigned. However, only a definitely assigned argument can be passed as a reference parameter.
    int m; // m not definitely assigned
    Func(ref m); // compile time error
    The argument corresponding to a reference parameter must be a modifiable variable (an lvalue); it cannot be a pure value or a const variable:
    Func(ref 42); // compile time error
    const int m = 42;
    Func(ref m); // compile time error
  • A parameter declared with an out modifier is a output parameter. An output parameter does not create a new storage location. Instead the output parameter is an alias for the variable given as the argument in the function member invocation. In effect an output parameter is another name for an existing variable.
    Note that the out modifier is required on both the function member declaration and on the function member invocation.
    For the purposes of definite assignment checking, an output parameter is considered initially unassigned. An output parameter must be definitely assigned at the end of its function.
    int m; // m not definitely assigned
    Func(out m); // OK, m now assigned
    The argument corresponding to a reference parameter must be a modifiable variable (an lvalue); it cannot be a pure value or a const variable:
    Func(out 42); // compile time error
    const int m = 42;
    Func(out m); // compile time error
  • In C#, and Java (but not C++) a function that expects no parameters must be declared with empty parentheses:
    int F(void)... // illegal in C# and Java
    The ref and out modifiers form part of the signature of a function. This means you can overload based on them (remember, the ref and out modifier must appear in the call). The ref and out modifiers are safe in the sense that only a ref argument can be bound to a ref parameter, only an out argument can be bound to an out parameter. However, it would be very easy to forget a ref or out modifier at the call site so it is best to avoid ref/out overloading.
    In C#, as in Java, you are not allowed to omit the name of a parameter. In C++ you are allowed to omit the name of the parameter in a function declaration and a function definition.
    int F(int /*noname*/)... // illegal in C# and Java
    In C#, as in Java, there are no default arguments (there are in C++). This is no great loss since in both C# and Java a constructor can call a sibling constructor. And default arguments are widely regarded as a bad idea in C++ anyway.
    In C#, as in Java, there is no way to specify a "readonly" parameter (other than value parameters for value types). There is in C++ (via const T * or const T &).
    C# in common with Java (but not C++) does not allow a cast to void:
    (void)Method(); // illegal in C# and Java
  • In C#, and Java (but not C++) a function that expects no parameters must be declared with empty parentheses:
    int F(void)... // illegal in C# and Java
    The ref and out modifiers form part of the signature of a function. This means you can overload based on them (remember, the ref and out modifier must appear in the call). The ref and out modifiers are safe in the sense that only a ref argument can be bound to a ref parameter, only an out argument can be bound to an out parameter. However, it would be very easy to forget a ref or out modifier at the call site so it is best to avoid ref/out overloading.
    In C#, as in Java, you are not allowed to omit the name of a parameter. In C++ you are allowed to omit the name of the parameter in a function declaration and a function definition.
    int F(int /*noname*/)... // illegal in C# and Java
    In C#, as in Java, there are no default arguments (there are in C++). This is no great loss since in both C# and Java a constructor can call a sibling constructor. And default arguments are widely regarded as a bad idea in C++ anyway.
    In C#, as in Java, there is no way to specify a "readonly" parameter (other than value parameters for value types). There is in C++ (via const T * or const T &).
    C# in common with Java (but not C++) does not allow a cast to void:
    (void)Method(); // illegal in C# and Java
  • As in C++ and Java, the return type is not considered part of the signature and cannot be used as basis for overloading. Note also that there is no return type covariance in C#.
    Like Java, C# does not allow global functions. All functions must be in the scope a class or struct; they must be function members.
    C#, like Java, has no concept of header files. All function declarations exist inline in the class/struct declaration.
    C#, like Java, allows an optional trailing semi-colon on a class declaration. However, C#, does not allow a trailing semi-colon on a function declaration (Java does) :
    There are no throw specifications in C#. This is a major difference to Java.
  • C# shares with Java (but not with C++) the rule that a block and its parent block cannot have a variable with the same name.
    All three languages allow a block to declare a local variable with the same name as an in scope field.
    All three languages do not allow a parameter to be redeclared as a local variable or an exception parameter:
    void Method(int parameter)
    {
    int parameter; // compile time error
    }
    void Method(int parameter)
    {
    try {
    ...
    }
    // compile time error
    catch (Exception parameter) {
    ...
    }
    }
  • In C# (as in Java, but unlike C++) there are no conversions (implicit or explicit) to or from bool. Ever. Nada. Nothing. Zip. This means that the expression inside the parentheses must be a genuine boolean expression.
    The definite assignmentrule of C# (and Java) understands the selection point introduced by an if statement (and the ?: ternary operator). A variable is only considered definitely assigned if all paths through the code (via static flow analysis) definitely assign to the variable. For example, the following generates a compile time error regardless of the contents of Function (which must return a bool):
    int m;
    if (Function())
    m = 42;
    int copy = m; // error: m not definitely assigned
    In C#, (again as in Java) the statement controlled by the if is an embedded-statement, which cannot be a declaration-statement. In other words, the following is illegal in C# and Java:
    if (condition())
    int useless; // declaration statement
    ...
    C#, (unlike C++) does not allow a variable to be declared as part of the controlling boolean expression:
    if (bool married = !bachelor(boy)) ...
  • definite assignment
    ability to reorder clauses
  • You can only switch on a user-defined type if that that type has a single implicit conversion to an integral type (including enum) or string.
  • no bool conversions
  • Reason for preferring != to < in the boolean continuation expression.
  • The C# foreach statement works on any collection that implements the IEnumerable interface which lives in the System.Collections namespace. Arrays implicity derive from the System.Array class which supports this interface meaning that a foreach statement can iterate through an array.
    The IEnumerable interface contains one operation:
    public interface IEnumerable
    {
    IEnumerator GetEnumerator();
    }
    IEnumerator is also an interface which lives in the System.Collections namespace. It provides a standard mechanism for iterating over a collection:
    public interface IEnumerator
    {
    bool MoveNext();
    object Current { get; }
    void Reset();
    }
    Current is a readonly property. Properties are fully covered later.

    The foreach expression can also be of a type deemed to be a "collection type". A collection type is defined by the following pattern:
    C contains a public instance method with the signature GetEnumerator() that returns a struct-type, class-type, or interface-type, which is called E in the following text.
    E contains a public instance method with the signature MoveNext() and the return type bool.
    E contains a public instance property named Current that permits reading the current value. The type of this property is said to be the element type of the collection type.
  • rules of finally interaction with goto, break, continue: 8.9.1 and 8.9.2 and 8.9.3
  • As a gesture to C++ programmers a struct declaration is allowed a trailing semi-colon. In fact, a Java class definition is allowed one too. It is best to get used to not using the trailing semi-colon since C# function members are not allowed a trailing semi-colon (they are in Java):
    class Example
    {
    // trailing ; illegal in C#, OK in Java
    public void Function( ) { } ;
    }
  • The basic syntax for declaring a C# constructor is the same as in Java and C++. The main difference is that C# constructors cannot declare a throw specification (since there are no throw specifications in C#).
    A struct will always have a compiler generated default constructor. If you don't declare a constructor for your struct the compiler generated default constructor exists. If you do declare a constructor for your struct the compiler generated default constructor still exists. This means that you cannot declare a user-defined default constructor for a struct (since then there would be two). Note that this rule does not apply to classes. The compiler generated default constructor zero initializes all instance fields of the object to zero:
    bool to false
    integral types (including char) to 0
    floating point types(including decimal) to 0.0
    enum types to 0 (this is a legal implicit cast)
    references types (which includes string) to null
    Note that the default accessibility of a struct and class constructor is private (as it is for fields). This is different to Java where the accessibility of the default constructor depends on the accessibility of the containing class.
    Note that in Java you can override the default constructor, and if you declare any constructor the compiler does not then generate the default constructor. Java also allows a method with the same name as a constructor (C# does not).
  • In C# a constructor can call a sibling constructor as shown on the slide. Note that in Java the syntax is subtley different; the chained call occurs inside the { body }
    // Java code
    public Point(int x, int y)
    {
    this(x, y, Colour.Red);
    }
    The general member-initialization-list syntax available in C++ is not legal syntax in C#.
    // C++ code
    Point(int initial_x, int initial_y)
    : x(initial_x), y(initial_y)
    {
    }
    There are no issues regarding a struct constructor calling a base class constructor since a struct cannot inherit from a class.
  • In a struct constructor this acts as an out parameter bound to the object being constructed. struct constructors must explicitly initialise all instance fields (these rules do not apply to class constructors).
    public BadPair(int x, int y)
    {
    this.x = x; // fails to initialise this.y
    }
    private int x, y; Instance fields of a struct can only be initialized in a constructor; they cannot be initialized using the variable initialisation syntax (again this is not true for class constructors):
    private int x;
    private int y = 0; // illegal in a struct
    In Java you can initialize a field in a "free block", for example:
    private Hiker arthur; // note semi-colon
    {
    arthur = new Hiker();
    }
    This is not legal syntax in C#.
  • ...
    The value of a static readonly field is dynamically loaded by the IL whereas the value of a const is statically loaded and is part of the IL itself. For example, consider the following code fragment:
    class Life
    {
    public static readonly question = 9 * 6;
    public const int answer = 42;
    static void Main()
    {
    Console.WriteLine(Life.question);
    Console.WriteLine(Life.answer);
    }
    }
    The IL generated from Main is as follows:
    ldsfld int32 Life::question
    call void [mscorlib]System.Console::Write(int32)
    ldc.i4.s 42
    call void [mscorlib]System.Console::Write(int32)
  • In C# a const field is implicit static. In Java a final field is not implicitly static.
    The first error is caused by attempting to initialize a const field in a constructor. A const field can only be initialized using the variable intialization syntax:
    The second error is caused by specifying the const int field with an explicit static modifier. A const field is implicitly static and can only be implicitly static.
    const int answer = 42; // now OK
    The third error is caused by failing to initialize the const field (which was erroneously attempted in the constructor).
    const int question = 9 * 6; // now OK
    The fourth error is caused by attempting to qualify a field of type Pair with the const modifier. A const modifier can only be applied to simple types (the types with a keyword name and a literal syntax), enums, and strings. Pair cannot be any of these types since an enum cannot be initialized using new (the only value type that can't) and Pair cannot be an alias for a simple type or string since there are no typedef's in C#.
    Note that const fields are not versioned whereas static readonly fields are.
  • A field declared with the static modifier is called a static variable. A static variable comes into existence when the type in which it is declared is loaded, and ceases to exist when the program terminates.
    The initial value of a static variable is the default value of the variable's type:
    all fields zero for a struct type
    null for reference types
    Remember, the static modifier cannot be applied to enum types or simple types. It can only be applied to user-defined struct types and class types. Note that since string is a class type (a reference type) it is possible to create a constant string using either syntax:
    const string firstName = "Arthur";
    static readonly string secondName = "Dent";
    string is the only type with this distinction.
    Like Java, static fields can only be accessed using the name of the enclosing type (in C++ you can use the typename or a variable).
  • In Java you can write code a static initialisation block (or two or three...) in a class declaration and that code will be executed once when the class is loaded.
    There is no equivalent of Java static initialisation blocks in C#. However, you can declare a single static constructor which serves the same purpose.
    A static constructor is called by the .NET VES and not by a programmer. This ensures that it is called, it is called only once, and it is called at the right time (before any use of the struct/class). Since the programmer does not call the static constructor the static constructor is not allowed any parameters. For the same reason the static constructor is not allowed to be qualified with a public, protected, private, or internal access modifier.
    why use a static constructor instead of a variable initializer? possibly to surround it with try block? would that work?

  • plain bitwise copy will never throw an exception
  • similarly you cannot change the behaviour that assignment does a simple bitwise copy.
    Again plain bitwise assignment will never throw an exception.
  • The true and false operators are rather bizarre. They can be used to allow && and || to be overloaded for user-defined types whilst retaining short circuit semantics.
  • All types referenced in an operator declaration must be at least as accessible as the operator itself. Although an operator must be declared public, it may be inside a struct/class with restricted accessibility (covered fully later).
    A few operators imposes additional restrictions as described in the C# language reference document.
  • The compound assignment operators cannot be directly overloaded in C#. However expressions of the form X op= Y are processed as X = X op Y, except that X is evaluated only once. For example, suppose C() is a method returning an in array, B() is a method returning an int, and C is also a method returning an int. In this case the expression:
    A()[B()] += C();
    causes the methods A, B, and C to be evaluated only once.
    The left hand operand of a compound assignment can be a property or indexer (covered later) as long as property or indexer has a get and a set accessor.
    The simple rule to remember is that the following is permitted:
    X op= Y
    only if both of the following are permitted:
    X op Y
    X = Y
  • The increment (++) and decrement (- -) operators can be overloaded for user-defined structs/classes in C#.
    The increment and decrement operators are unique in that they can be used as prefix operators (++m) or as postfix operators (m++). In C++ you can provide one operator for the prefix version (which takes a single arg) and another operator for the postfix version (which takes a dummy second arg of type int; noone claims this to be elegant but it does work).
    In C# a single operator is used for both the prefix and postfix versions. The compiler arranges for the result of a prefix call to be the value of the operand before the call takes place, and the value of a postfix call to be the result of the call.
    This compiler magic works when the type being overloaded with ++ or - - is a struct type. However, if the type is a class (a reference type) then the value of the perfix call and postfix call will be the same. This is a minor nit though because operator overloading is a technique that naturally fits with value types and doesn't really make sense for reference types.
    The parameter type and return type of an increment and decrement operator must be the containing type.
  • Some operators naturally come in pairs. For example if you can compare two values to see if they are equal using the == operator is is reasonable to assume you can also compare them using the != operator. C# enforces this. If you declare one you must declare the other or the program will not compile. The == != are also important as a pair because nullable types (eg database booleans that can the value true false or null) it is not the case the a == b implies !(a != b).
    All types referenced in an operator declaration must be at least as accessible as the operator itself. Although an operator must be declared public, it may be inside a struct/class with restricted accessibility (covered fully later).
    A few operators imposes additional restrictions as described in the C# language reference document.
  • The operator true and operator false pair are designed for tri-state nullable types such as database booleans that can hold the value true, false, or null.
    Implementing operator true and operator & for a struct or class has the effect of creating an operator && for the type in question. This operator will retain short circuit semantics but will not return a built-in bool but the type in question.
    Implementing operator false and operator | for a struct or class has the effect of creating an operator || for the type in question. This operator will retain short circuit semantics but will not return a built-in bool but the type in question.
    Interested readers should refer to a complete example in the struct chapter of the language reference.
  • A conversion operator converts from a source type to a target type. The source type is indicated by the type of the conversion operator. The target type is indicated by the return type of the conversion operator. A class or struct is permitted to declare a conversion from source S to target T provided all of the following are true:
    S and T are different types
    Either S or T is the containing struct or class
    Neither S nor T is object
    Neither S nor T is an interface type
    T is not a base class of S (only possible if T and S are not structs)
    S is not a base class of T (only possible if T and S are not structs)
    the declaration would create an implicit and an explicit conversion from S to T
    From the second rule it follows that you can declare a user-defined conversion from a struct or class to a simple type (such as int) and vice versa but never from a simple type to another simple type.
    A user-defined conversion is the only form of function for which the return type is part of the signature.
    In C# a single argument constructor is never a converting constructor (as it is in C++ if the constructor is not explicit).
  • A conversion operator converts from a source type to a target type. The source type is indicated by the type of the conversion operator. The target type is indicated by the return type of the conversion operator. A class or struct is permitted to declare a conversion from source S to target T provided all of the following are true:
    S and T are different types
    Either S or T is the containing struct or class
    Neither S nor T is object
    Neither S nor T is an interface type
    T is not a base class of S (only possible if T and S are not structs)
    S is not a base class of T (only possible if T and S are not structs)
    the declaration would create an implicit and an explicit conversion from S to T
    From the second rule it follows that you can declare a user-defined conversion from a struct or class to a simple type (such as int) and vice versa but never from a simple type to another simple type.
    A user-defined conversion is the only form of function for which the return type is part of the signature.
    In C# a single argument constructor is never a converting constructor (as it is in C++ if the constructor is not explicit).
  • common bounds checking must be duplicated inside the get and the set accessor.
  • You can only use a property on a definitely assigned variable. For example:
    Pair p;
    p.X = 0; // compile time error
    This is because the set accessor of the X field can contain any statements the programmer wishes. It does not even have to set a field since the property could be the implementation of a derived (deduced) attribute.
    Pair p = new Pair();
    p.X = 0; // OK
  • Transcript of "Csharp In Detail Part1"

    1. 1. © { JSL } 1 C#inDetail Jon Jagger Software Trainer, Designer, Consultant www.jaggersoft.com jon@jaggersoft.com { JSL } Part 1
    2. 2. © { JSL } 2 BlatantAdvert  an interactive, friendly, expert instructor  Jon has worked for Microsoft using C#  lots of great exercises  to make sure you understand  even more slides  with detail, explanations, and rationales  full slide notes  include careful comparisons with C++ and Java C# in Detail is also available as an instructor led course
    3. 3. © { JSL } 3 Agenda  overview  built-in value types  enums  parameters  control flow  structs  constructors  fields  operators  indexers  properties
    4. 4. © { JSL } 4 C# Programming Fundamentals Objects Relationships Systems Overview
    5. 5. © { JSL } 5 C#Features static typing runtime polymorphism operator overloading exceptions multiple public realization non deterministic finalization multi threading compile time polymorphism ? value types garbage collection single public inheritance unified type system Object super base class virtual execution system reflection reference types C#, C++ and Java C# and JavaC# and C++ C#
    6. 6. © { JSL } 6 HelloUniverse Hiker.cs using System; public class Hiker { public static void Main() { int result; result = 9 * 6; int tirteen; tirteen = 13; Console.Write(result / tirteen); Console.Write(result % tirteen); } } // An Irish program that find the answer // to life, the universe, and everything C:Sharp>csc Hiker.cs C:Sharp>Hiker.exe 42// single-line comment
    7. 7. © { JSL } 7 MSIL C:Sharp>ildasm Hiker.exe
    8. 8. © { JSL } 8 VES  intermediate language, IL  loading managed code including resolving names  conversion of IL into native code  verification of the type safety of the IL  verification of integrity of the metadata  garbage collection services  initiation, propagation, and intercepting exceptions  profiling and debugging services  management of threads, contexts, and remoting
    9. 9. © { JSL } 9 FortyTwo  C# programs are constructed from tokens Hiker.cs /* */ using System; public class Hiker { public static void Main() { int result; result = 9 * 6; int tirteen; tirteen = 13; Console.Write(result / tirteen); Console.Write(result % tirteen); } } /* An Irish program that find the answer * to life, the universe, and everything */ multi-line comment (non nestable)
    10. 10. © { JSL } 10 Tokens  five kinds of tokens in C# programs token examples identifiers Hiker Main result keywords public class int literals 9 6 13 operators + - * / % = punctuators ; { } ,
    11. 11. © { JSL } 11 Pre-processing  C# has a sensibly limited "preprocessor"  no #include, no #pragma  #define, but no macros #undef PP_TOKEN #if pp-expression #line 42 "hhg.cs" #error pp-msg#region pp-msg #define PP_TOKEN #elif pp-expression #else #endif #warning pp-msg#endregion pp-msg #if 0  #if false
    12. 12. © { JSL } 12 Identifiers  rules  made of letters and digits  must start with a letter  underscore is a letter  case sensitive  recommendations  don't use underscores  don't abbreviate  don't use hungarian  follow style guidelines different Different answer42 42Answer    rare_style privateStyle PublicStyle msg message !CLS camel Case Pascal Case
    13. 13. © { JSL } 13 Keywords  some identifiers have a fixed meaning using System; public class Hiker { public static void Main() { int result; result = 9 * 6; int tirteen; tirteen = 13; Console.Write(result / tirteen); Console.Write(result % tirteen); } } /* An Irish program that find the answer * to life, the universe, and everything */
    14. 14. © { JSL } 14 KeywordTable  76 keywords (+ 5 ish) abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual void while get set value add remove These are sometimes reserved Any keyword can be used as an identifier if preceeded by @
    15. 15. © { JSL } 15 Literals  some tokens represent fixed values type literal bool true false double 3.1415 char 'X' int 9 6 13 42 string "Hello" truth floating point integers characters sequences of characters object nullnothing
    16. 16. © { JSL } 16 Operators  some tokens represent fixed actions symbol category + - * / % arithmetic && || ! logical < <= > >= relational == != equality = assignment & | ^ ~ << >> bitwise
    17. 17. © { JSL } 17 Punctuators  some tokens group or separate  { and } form scoped blocks  semi-colons mark the end of a simple statement using System; public class Hiker { public static void Main() { int result; result = 9 * 6; int tirteen; tirteen = 13; Console.Write(result / tirteen); Console.Write(result % tirteen); } }
    18. 18. © { JSL } 18 Declarations  declarations introduce variables into a scope  a variable has an identifier and a type  a variable's type can never change using System; public class Hiker { public static void Main() { int result; result = 9 * 6; int tirteen; tirteen = 13; Console.Write(result / tirteen); Console.Write(result % tirteen); } } type identifier ; type identifier, another ;
    19. 19. © { JSL } 19 Expressions  expressions compute things!  an expression yields a value  an expression must also have a side-effect using System; public class Hiker { public static void Main() { int result; result = 9 * 6; int tirteen; tirteen = 13; Console.Write(result / tirteen); Console.Write(result % tirteen); } }
    20. 20. © { JSL } 20 TwoTypes  value types  variables contain their own data directly  local variables always live on the stack  reference types  variables refer to their data indirectly  local variables refer to objects on the heap object valueenum class interface [ ]array delegate struct value object object object @ @ @ @
    21. 21. © { JSL } 21 C# Programming Fundamentals Objects Relationships Systems bool
    22. 22. © { JSL } 22 bool  bool is a keyword  an alias for System.Boolean  only values are true and false bool love = true; bool teeth = false; System.Boolean love = true; System.Boolean teeth = false; using System; ... Boolean love = true; Boolean teeth = false; Boolean love = true; Boolean teeth = false;    
    23. 23. © { JSL } 23 System.Boolean namespace System { public struct Boolean ... { // static fields public static readonly string FalseString; public static readonly string TrueString; ... // static methods public static bool Parse(string); ... // instance methods public override string ToString(); ... } } bool b = bool.Parse(Console.ReadLine()); Console.WriteLine(true.ToString()); Console.WriteLine(b.ToString());
    24. 24. © { JSL } 24 boolOperators int tens = 9 * 6 / 13; int units = 9 * 6 % 13; bool isFour = tens == 4; bool isTwo = units == 2; bool hhg; hhg = isFour && isTwo; hhg = !(isFour && isTwo); hhg = !isFour || !isTwo; hhg = !hhg; assignment = in-equality == != logical ! && || short circuiting
    25. 25. © { JSL } 25 boolConversios  no implicit conversions to bool  ever  none  nada  zip  under any circumstances whatsoever
    26. 26. © { JSL } 26 C# Programming Fundamentals Objects Relationships Systems byteshortintlong
    27. 27. © { JSL } 27 IntegerTypes type bits System. short 16 Int16 int 32 Int32 long 64 Int64 sbyte 8* SByte ushort 16 Uint16 uint 32 UInt32 ulong 64 UInt64 byte 8* Byte CLS? yes yes yes no no no no yes signed? yes yes yes yes no no no no
    28. 28. © { JSL } 28 System.Int32 namespace System { public struct Int32 ... { // static fields public const int MaxValue; public const int MinValue; ... // static methods public static int Parse(string); ... // instance methods public override string ToString(); ... } } int i = 42; System.Int32 count = 0; Console.WriteLine(42.ToString()); Console.WriteLine(count.ToString()); Console.WriteLine(int.MaxValue);
    29. 29. © { JSL } 29 IntegerLiterals decimal-integer-literal: decimal-digits integer-type-suffixopt decimal-digits: decimal-digit decimal-digits decimal-digit decimal-digit: one of 0 1 2 3 4 5 6 7 8 9 integer-type-suffix: one of U u L l UL Ul uL ul LU Lu lU lu hexdecimal-integer-literal: 0x hex-digits integer-type-suffixopt 0X hex-digits integer-type-suffixopt hex-digits: hex-digit hex-digits hex-digit hex-digit: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F no octal
    30. 30. © { JSL } 30 IntegerOperators assignment = in-equality == != relational < > <= >= arithmetic + - * / % bitwise | & ^ ~ shift << >> inc/dec ++ -- compound assignment
    31. 31. © { JSL } 31 PrimaryOperators grouping (x) access x.y method call f(x) indexing a[x] post-increment x++ post-decrement x-- stack allocation stackalloc constructor call new type retrieval typeof size retrieval sizeof checking (un)checked also -> (unsafe) arrays only unsafe
    32. 32. © { JSL } 32 Precedence primary see previous slide unary + - ! ~ ++x –-x (T)x multiplicative * / % additive + - shift << >> relational < > <= >= is as equality == != bitwise & ^ | boolean && || ?: assignment = *= /= %= += -= ...
    33. 33. © { JSL } 33 Associativity  rule 1  except for the assignment operators all binary operators are left-associative  rule 2  the assignment operators and the conditional operator (?:) are right-associative x + y + z  (x + y) + z x = y = z  x = (y = z)
    34. 34. © { JSL } 34 EvaluationOrder  operands are evaluated strictly left to right  same as in Java, unspecified in C++ int m = 2; int answer = ++m * ++m + ++m * ++m; 3 * 4 + ++m * ++m 12 + ++m * ++m 12 + 5 * ++m 12 + 5 * 6 12 + 30 3 * ++m + ++m * ++m 42
    35. 35. © { JSL } 35 IntegerOverflow  DivideByZeroException, OverflowException  un/checked expressions  un/checked { statementsopt } int m = int.Parse(Console.ReadLine()); Func(checked(m * 2)); m = checked(m * 2); checked { F(m * 2); m *= 2; } Func(m * 2); m *= 2; Func(unchecked(m * 2)); m = unchecked(m * 2); unchecked { F(m * 2); m *= 2; } always checked never checked csc /checked+ *.cs csc /checked- *.cs
    36. 36. © { JSL } 36 IntegerMSIL  integer MSIL instructions come in two forms  one checks for overflow ( eg mul.ovf )  one doesn't check for overflow ( eg mul ) int a, b, c; ... .locals(int32 V0, int32 V1, int32 V2) int c = checked(a * b); ldloc.0 ldloc.1 mul.ovf stloc.2 int c = a * b; ldloc.0 ldloc.1 mul stloc.2 C# MSIL
    37. 37. © { JSL } 37 IntegerShifting  never throw exceptions  (u)int shift  count & 0x1F  (u)long shift  count & 0x3F int operator <<( int x, int count); long operator <<( long x, int count); uint operator <<( uint x, int count); ulong operator <<(ulong x, int count); int operator >>( int x, int count); long operator >>( long x, int count); uint operator >>( uint x, int count); ulong operator >>(ulong x, int count); arithmetic shift logical shift MSIL == shl MSIL == shr and shr.un
    38. 38. © { JSL } 38 IntegerConversions  implicit, widening conversions  never lose information, never throw exception  explicit narrowing conversions (casts)  may lose information, may throw exception short s; int m; .locals(int16 V0, int32 V1) ldloc.1 conv.ovf.i2 stloc.0 ldloc.1 conv.i2 stloc.0 s = checked((short)m); s = unchecked((short)m); s = (short)m; ? csc /checked+ csc /checked- C# IL
    39. 39. © { JSL } 39 sbyte short int long sbyte short int long byte ushort uint ulong byte ushort uint ulong signed unsigned signedunsigned ConversionTable • I I I E • I I E E • I E E E • E E E E E E E E E E E E E E E E E I I I E E I I E E E I E E E E • I I I E • I I E E • I E E E •
    40. 40. © { JSL } 40 C# Programming Fundamentals Objects Relationships Systems floatdouble
    41. 41. © { JSL } 41 F.P.Types type bits System. float 32 Single double 64 Double CLS sig. figs 157 yes yes MSIL float32 float64 ± 3.4x1038 ± 1.7x10308range suffix F f D d
    42. 42. © { JSL } 42 System.Double namespace System { public struct Double ... { // static fields public const double Epsilon; public const double MaxValue; public const double MinValue; public const double NaN; public const double NegativeInfinity; public const double PositiveInfinity; ... // static methods public static bool IsInfinity(double); public static bool IsNaN(double); public static double Parse(string); ... // instance methods public override string ToString(); ... } }
    43. 43. © { JSL } 43 F.P.Literals real-literal: digits . digits exponentopt suffixopt . digits exponentopt suffixopt digits exponent suffixopt digits suffix digits: digit digits digit digit: one of 0 1 2 3 4 5 6 7 8 9 exponent: e signopt digits E signopt digits sign: one of + - suffix: one of F f D d M m Truth(1.2E-3D is double); Truth(.89F is System.Single); Truth(123D is double); OK(123D.ToString()); OK(123.0.ToString()); OK(123.ToString()); Fails(123.); Fails(123.D); Fails(123..ToString()); compile time errors
    44. 44. © { JSL } 44 F.P.Operators  mostly the same as the integers  modulus % is permitted (it's not in C++)  shift operators are not permitted  FP arithmetic never throws exceptions  result too small  +/- zero  result too large  +/- infinity  invalid operation  NaN  either operand NaN  Nan
    45. 45. © { JSL } 45 F.P.Conversions  double  float  explicit conversion  never throws  integer  floating point  implicit conversion  never throws  may lose precision, never loses magnitude  floating point  integer  explicit conversion  may throw OverflowException (Beta-2 language specification says it won't)
    46. 46. © { JSL } 46 C# Programming Fundamentals Objects Relationships Systems decimal
    47. 47. © { JSL } 47 decimalType  type bits System. decimal 128 Decimal CLS sig. figs 28 yes ± 7.9x1028range suffix M m float 32 double 64 157 ..x1038 ..x10308 F f D d DoubleSingle yesyes
    48. 48. © { JSL } 48 System.Decimal namespace System { public struct Decimal ... { // static fields public static readonly decimal MaxValue; public static readonly decimal MinusOne; public static readonly decimal MinValue; public static readonly decimal One; public static readonly decimal Zero; ... // static methods public static decimal Parse(string); ... // instance methods public override string ToString(); public double ToDouble(); ... } }
    49. 49. © { JSL } 49 moreConversions  float / double  decimal  explicit conversion (FP have greater range)  always checked, may throw  decimal  float / double  explicit conversion (FP has less precision)  never throws, may lose precision  decimal  integral  explicit conversion (decimal has greater range)  always checked, may throw OverflowException  integral  decimal  implicit conversion  never throws, never loses information
    50. 50. © { JSL } 50 C# Programming Fundamentals Objects Relationships Systems char
    51. 51. © { JSL } 51 charType type bits System. char 16 Char CLS yes 0x0000 0xFFFF min max Unicode 3.0 You idiot, that's a chair
    52. 52. © { JSL } 52 System.Char namespace System { public struct Char ... { // static fields public const char MaxValue; public const char MinValue; ... // static methods public static bool IsDigit(char); public static bool IsLetter(char); public static bool IsWhiteSpace(char); public static string ToString(char); ... // instance methods public override string ToString(); ... } }
    53. 53. © { JSL } 53 charLiterals character-literal: ' character ' character: single-character simple-escape-character hex-escape-sequence unicode-escape-sequence single-character: any char except ' (U+0027), (U+005C), and new-line simple-escape-character: one of ' " 0 a b f n r t v hex-escape-sequence: x xdigit xdigiitopt xdigitopt xdigitopt xdigit: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F unicode-escape-sequence: u xdigit xdigit xdigit xdigit U xdigit xdigit xdigit xdigit xdigit xdigit xdigit xdigit no octal escape
    54. 54. © { JSL } 54 charConversions  char is classified as an integral type  you can do char arithmetic  implicit conversion from char to  ushort, int, uint, long, ulong, float, double, decimal  explicit conversion from char to  sbyte, byte, short  no implicit conversions to char  even for sbyte, byte, and short
    55. 55. © { JSL } 55 C# Programming Fundamentals Objects Relationships Systems enum
    56. 56. © { JSL } 56 enumDeclaration  a user-declared value-type enum Suit { Clubs, Diamonds, Hearts, Spades }; class Example { static void Main() { ... Suit dig = Spades; ... Suit trumps = Suit.Clubs; ... } } each enum declaration creates a new declaration space optional semi-colon compile time error okay
    57. 57. © { JSL } 57 enumNotes enum Suit : int { Clubs, Diamonds, Hearts = 42, Spades, } the underlying integer type can be any of the basic 8 integer types and defaults to int (not char) named constants can be initalized from constants; they default to the previous constant + 1 optional comma after last named constant
    58. 58. © { JSL } 58 enumUse  enums implicitly derive from System.Enum Suit trumps = Suit.Club; string[] names = System.Enum.GetNames(trumps.GetType()); ... Console.Write(names[0]); // Clubs Console.Write(trumps); // Clubs Console.Write("{0}", trumps); // Clubs Console.Write(trumps.ToString()); // Clubs Console.Write((Suit)42); // 42 namespace System { public class Enum ... { // static methods public static string[] GetNames(Type); ... // instance methods public override string ToString(); // constructor protected Enum(); } }
    59. 59. © { JSL } 59 enumOperators  enum variables can mostly be used as ints assignment = in-equality == != relational < > <= >= arithmetic + - * / % bitwise | & ^ ~ shift << >> inc/dec ++ -- yes yes yes yes no yes yes
    60. 60. © { JSL } 60 enumConversions  implicit conversion  literal 0 to any enum type  explicit conversions  from enum to enum via underlying type  from enum to numeric type (including char)  from numeric type (including char) to enum The set of values that an enum can take on is not limited by its enum members. Any value of the underlying type of the enum can be cast to the enum type, and is a distinct, valid value of that type. C# language spec (0.26)
    61. 61. © { JSL } 61 Terminology  two kinds of value type  enum types  struct types  two kinds of struct types  user-defined struct type  no literal syntax  simple struct types  integral types ( includes char )  floating point types ( includes decimal )  bool
    62. 62. © { JSL } 62 C# Programming Fundamentals Objects Relationships Systems Parameters
    63. 63. © { JSL } 63 CopyParameters  a plain parameter is a copy of the argument  no frills bitwise copy  the argument must be definitely assigned  argument can be an "rvalue" static void Method(Suit parameter) { parameter = Suit.Hearts; } static void Main() { Suit arg = Suit.Clubs; Console.Write(arg); Method(arg); Console.Write(arg); } Clubs Clubs
    64. 64. © { JSL } 64 refParameters  a ref parameter is an alias for the argument  no copy takes place  argument must be definitely assigned  argument must be an "lvalue"  ref required on argument and parameter static void Method(ref Suit parameter) { parameter = Suit.Hearts; } static void Main() { Suit arg = Suit.Clubs; Console.Write(arg); Method(ref arg); Console.Write(arg); } Clubs Hearts
    65. 65. © { JSL } 65 outParameters  an out parameter is an alias for the argument  no copy takes places  argument need not be definitely assigned  parameter must be definitely assigned  argument must be an "lvalue"  out required on argument and parameter static void Method(out Suit parameter) { parameter = Suit.Hearts; } static void Main() { Suit arg; //Console.Write(arg); Method(out arg); Console.Write(arg); } Hearts
    66. 66. © { JSL } 66 inParameters?  readonly, const and in, are all C# keywords  they cannot be applied to parameters  ref / out parameters always grant write access  for value types simply pass by copy argument parameter @ @ optional required Copy ref outClubs initialize Clubs Clubs Clubs
    67. 67. © { JSL } 67 ParameterNotes  sdclass Notes { ... Good( int copy) ... ... Error(ref int alias) ... ... Error(out int alias) ... ... Error(float /*noname*/) ... ... Error(double d = 0.0) ... ... Error(const ref Wibble w) ... ... Error(void) ... } struct BadPair { ref int x; out int y; } ref and out cannot be used as field modifiers (or return type modifiers) ref, out modifier is part of signature must name parameter no default arguments (overload instead) no readonly parameters no void parameter can't overload based soley on ref out
    68. 68. © { JSL } 68 MoreNotes class Notes { int Error() { ... } double Error() { ... } } return type is not part of signature int Global() { ... } no trailing semi-colon no global functions class Notes { int Error(); void AlsoError() {}; } definition must be inline
    69. 69. © { JSL } 69 C# Programming Fundamentals Objects Relationships Systems ControlFlow
    70. 70. © { JSL } 70 Blocks  a block and its parent block  cannot have a variable with the same name  sibling blocks  can have variables with the same name int m; { int m; ... } compile time error OK { int m; ... } { int m; ... }
    71. 71. © { JSL } 71 if  no built-in conversions to/from bool  System.Convert.ToBoolean(int i) exists though  definite assignment consequences  just like in Java if (number % 2 == 0) parity = "odd"; else parity = "even"; if ( boolean-expression ) embedded-statement else embedded-statement if (number % 2 == 0) string parity = "even"; ... OK compile time error string parity = number % 2 == 0 ? "odd" : "even"; ternary operator
    72. 72. © { JSL } 72 switch  usual syntax  switch on integral types  case labels must be compile time constants  etc switch (trumps) { case Suit.Clubs: ... break; case Suit.Hearts: ... break; case Suit.Diamonds: ... break; case Suit.Spades: ... break; default: ... break; }
    73. 73. © { JSL } 73 caseNotes  unusual syntax  you can switch on a string  fall through is illegal, even on default clause  you can goto a case/default label ! void Func(string option) { switch (option) { case "label": goto case "jump": case "jump": goto default; case "quit": return; case "spin": for(;;){ } case "unwind": throw new Exception(); default: break; } }
    74. 74. © { JSL } 74 while/do  standard Java,C++ like syntax int m = 0; while (m != 10) { Console.Write("{0} ", m); m++; } int m = 0; do { Console.Write("{0} ", m); m++; } while (m != 10) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
    75. 75. © { JSL } 75 for  for statement  declared variables are scoped to for statement for (int m = 0; m != 10; m++) { Console.Write("{0} ", m); } for (int m = 0; m != 10; m++) { Console.Write("{0} ", m); } 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
    76. 76. © { JSL } 76 foreach  from shell, VB, PERL, etc  works on any collection, including [ ] arrays using System.Collections; class Example { static void Main() { ArrayList numbers = new ArrayList(); ... // fill numbers with 0 through 9 ... foreach (int number in numbers) { Console.Write("{0} ", number); } } } 0 1 2 3 4 5 6 7 8 9 ArrayList  C++ vector<>
    77. 77. © { JSL } 77 foreachNotes  foreach ( type identifier in expression )  type and identifier declare an iteration variable  implicitly readonly, can't be ref or out parameter  expression must be either  an IEnumerable collection, or  a "collection type"  conversion must exist, could throw ArrayList numbers = new ArrayList(); ... // fill numbers with 0 through 9 ... IEnumerator ie = numbers.GetEnumerator(); while (ie.MoveNext()) { int number = (int)ie.Current; Console.WriteLine(number); }
    78. 78. © { JSL } 78 continue/break  no labelled break statement int m = 0; for (;;) { Console.Write("{0} ", m); m++; if (m != 10) continue; else break; } 0 1 2 3 4 5 6 7 8 9
    79. 79. © { JSL } 79 C# Programming Fundamentals Objects Relationships Systems struct
    80. 80. © { JSL } 80 structDeclaration  a user-defined value-type struct Pair { public int X, Y; }; optional semi-colon by convention public names start with an uppercase letter (PascalCase) struct Pair { private int x, y; } ...and private names start with a lowercase letter (camelCase) struct Pair { int x, y; } default access is private
    81. 81. © { JSL } 81 structCreation  a struct local variable lives on the stack  is not definitely assigned, just like int  can always be initialised with a default c'tor call p.X stack ? ?p.Y p.X 0 0p.Y ... static void Main() { Pair p; Console.Write(p.X); ... } ... static void Main() { Pair p = new Pair(); Console.Write(p.X); ... } compile time error
    82. 82. © { JSL } 82 structUse  usual dot operator to access field  field must be assigned before its value is used  default c'tor default initialises fields zero/false/null ... static void Main() { Pair p; p.X = 0; Console.Write(p.X); } ... static void Main() { Pair p = new Pair(); Console.Write(p.X); } p.X stack 0 ?p.Y p.X 0 0p.Y
    83. 83. © { JSL } 83 structConstructor  unusual rules  compiler declares default c'tor  you cannot declare the default c'tor  default c'tor zero-initialises all instance fields struct Pair { } compile time error struct Pair { public Pair(int x, int y) {...} } compiler declares a default c'tor struct Pair { public Pair() { ... } } compiler declared default c'tor still exists
    84. 84. © { JSL } 84 :this(...)  a c'tor can call a sibling c'tor  syntax is similar to C++  no general member-init-list syntax though struct ColoredPoint { public ColoredPoint(int x, int y) : this(x, y, Colour.Red) { } public ColoredPoint(int x, int y, Colour c) { ... } ... private int x, y; private Colour c; }
    85. 85. © { JSL } 85 instanceFields  instance fields...  are default initialised in compilers default c'tor  must be explicitly initialised in users c'tor struct BadPair { public BadPair(int x, int y) { this.x = x; } private int x; private int y = 0; } compile time error: one instance field not intialised okay: all instance fields explicitly initialised struct GoodPair { public GoodPair(int x, int y) { this.x = x; this.y = y; } private int x, y; } compile time error: instance field cannot be intialised here
    86. 86. © { JSL } 86 readonlyFields  readonly instance fields...  are instance fields that cannot be assigned to compile time errors struct Pair { public Pair(int x, int y) { this.x = x; this.y = y; } public void Reset() { x = 0; y = 0; } private readonly int x, y; } this declares Pair as an immutable value
    87. 87. © { JSL } 87 constFields  const fields are implicitly static  only simple types, enums, & string can be const  const fields require a variable initialiser  must be initialized to compile time constant value struct Pair { private const int x = 0, y = 0; } struct BadFields { ... BadFields(...) { question = 9 * 6; } ... static const int answer = 42; ... const int question; ... const Pair origin = new Pair(); } OK compile time errors this declares Pair with no instance fields ... implicitly static ... can't initialize here ... not initialized ... Pair not simple type
    88. 88. © { JSL } 88 staticFields  to declare static fields of other types  use static keyword!  static fields are default initialised  static fields can use variable initialisers  access is via typename only struct Pair { ... static Pair origin; ... static Pair topLeft = new Pair(10,20); ... static AnyClass field; ... static string both = "Arthur"; } Pair p = new Pair(); ... F(p.Origin); F(Pair.Origin); compile time error okay
    89. 89. © { JSL } 89 LocalVariables  local variables can be declared const  but not static, and not readonly  and const is only for simple types  must be initialized to compile time constant value struct GoodExample { ... void Func() { const int answer = 42; const Suit trumps = Suit.Club; } } OK struct BadExample { ... void Func() { const int lv = F(); static Pair origin = ...; readonly Pair p = ...; } } compile time errors
    90. 90. © { JSL } 90 staticConstructor  a static c'tor initialises the type  can initialize static fields but not const fields  called by VES when the type is loaded  cannot be called, no access modifier allowed struct GoodExample { static GoodExample() { origin = new Pair(0,0); } ...static readonly Pair origin; } OK struct BadExample { public static BadExample() { x = 42; } ...const int x; } compile time errors
    91. 91. © { JSL } 91 CopyConstructor?  you can declare a "copy constructor"  it is not called for value parameters/returns  a copy is always a plain bitwise copy struct Pair { ... Pair(Pair other) { ... } ... } struct Pair { ... Pair Func() ... ... void Func(Pair copy) { Pair p = new Pair(copy); } } calling this does not result in infinite recursion these do not call the copy c'tor only this does
    92. 92. © { JSL } 92 CopyAssignment?  you cannot overload simple assignment  a copy is always a plain bitwise copy struct Pair { public static Pair operator=(Pair lhs, Pair rhs) { ... } ... } struct Pair { ... void Func(Pair lhs, Pair rhs) { lhs = rhs; ... } } you can't do this. compile time error simple assignment
    93. 93. © { JSL } 93 C# Programming Fundamentals Objects Relationships Systems Operators
    94. 94. © { JSL } 94 Overloading  you can  overload most operators  you can't  create new operators  change the multiplicity or precedence  change the associativity or order of evaluation  change the meaning of built in operators unary + - ! ~ ++ -- true false binary + - * / % & | ^ << >> == != > < >= <=
    95. 95. © { JSL } 95 operatorSyntax  operators are always defined as  public static methods (never virtual)  copy parameters only (not ref-out )  one+ parameter must be of containing type struct Meter { ... public static Meter operator + (Meter lhs, Meter rhs) { return new Meter(lhs.value + rhs.value); } ... } don't forget the new void Func(Meter lhs, Meter rhs) { Stuff(lhs + rhs); }
    96. 96. © { JSL } 96 Assignment  you can't overload assignment, but this... X op= Y X = X op Y is processed as this... except that X is evaluated only once public static Meter operator + (Meter lhs, Meter rhs) { ... } void Func(Meter lhs, Meter rhs) { lhs += rhs; ... }
    97. 97. © { JSL } 97 ++--  you can overload ++ and --  a single operator supports prefix and postfix  prefix returns the result of the call  postfix returns the operand before the call struct Meter { public static Meter operator ++ (Meter arg) { arg.value++; return arg; } ... } Meter distance; ... postfix = distance++; Meter distance; ... prefix = ++distance;
    98. 98. © { JSL } 98 operatorFamilies  some operators have natural partners  you can't have one without the other struct Meter { public static bool operator == (Meter lhs, Meter rhs) ... public static bool operator != (Meter lhs, Meter rhs) ... } true false == != < > <= >=
    99. 99. © { JSL } 99 operatortrue/false  designed for tri-state boolean types  eg SQL types: true, false, Null  also have the effect of  creating an implicit conversion to bool  can overload && || in combination with & | struct DBaseBool { public static bool operator false (DBbaseBool arg) ... public static bool operator true (DBbaseBool arg) ... }
    100. 100. © { JSL } 100 Conversions  must be public and static  must be implicit or explicit  implicit : compiler can call, should never throw  explicit : compiler can't call, cast required, may throw struct DBaseBool { public static implicit operator DBbaseBool (bool from) ... public static explicit operator bool (DBbaseBool from) ... }
    101. 101. © { JSL } 101 Example  "readonly" local variable struct ConstInt { public ConstInt(int value) { this.value = value; } public static implicit operator int(ConstInt from) { return from .value; } private readonly int value; } class Example { ... public void Method() { ConstInt local = new ConstInt(42); local++; // compile time error ... } }
    102. 102. © { JSL } 102 ConversionNotes  implicit conversion resolution  optional standard implicit conversion  user defined implicit conversion  optional standard implicit conversion  explicit conversion resolution  optional standard explicit conversion  user defined implicit or explicit conversion  optional standard explicit conversion a single argument constructor is never a converting constructor you cannot create conversions to interfaces
    103. 103. © { JSL } 103 C# Programming Fundamentals Objects Relationships Systems Indexers
    104. 104. © { JSL } 104 []  indexers provide [ ] like syntax of use  always an instance member, can be virtual  no ref-out parameters  can be overloaded class DoubleArray { ... public double this [int index] { ... } ... } an indexer is not an operator DoubleArray marks; ... marks[2] = 34.29; ... if (marks[0] > 42.0) ... no parentheses this is a keyword
    105. 105. © { JSL } 105 getandset  indexers can only contain accessors  get { accessor } for read context  set { accessor } for write context class DoubleArray { ... public double this [int index] { get { return ...; } set { ... = value; } } ... } marks[2] = 34.29; if (marks[0] > 50.0) ...
    106. 106. © { JSL } 106 getorset  an indexer with no set accessor  is a read-only indexer  and indexer with no get accessor  is a write-only indexer class Hand { ... public Card this [int index] { get { return ... } } } void Cheat(Hand current) { Card ace = MakeAce(Suit.Spades); ... current[0] = ace; } compile time error
    107. 107. © { JSL } 107 IndexerNotes  indexers compared to arrays  indexers can use multiple parameters  indexers can use non integer indexes  indexers can be overloaded  indexers can be declared in an interface interface IMatrix { ... double this [int row, int col] { get; set; } ... }
    108. 108. © { JSL } 108 C# Programming Fundamentals Objects Relationships Systems Properties
    109. 109. © { JSL } 109 getandsetAgain  an object oriented smart field  get and set accessors  instance property can be virtual struct Pair { ... public int X { get { return x; } set { x = value; } } private int x, y; } Pair p; ... p.X = 0; ... Console.Write(p.X); note no ( ) here and capital X
    110. 110. © { JSL } 110 staticProperties  properties can be static  unlike indexers class Console { ... public static readonly TextWriter Out { get { ... } } private static TextWriter out = null; } struct DateTime { ... public static DateTime Today { get { ... } } ... } possible lazy creation
    111. 111. © { JSL } 111 PropertyNotes  properties  are not lvalues, can't be ref-out args  can't be void  can't take arbitrary parameters  can be virtual  instance properties can go in an interface interface IAccount { ... decimal Balance { get; } ... }
    112. 112. © { JSL } 112 Summary  .NET, IL, CLS, CLR, VES  stack values – enum, struct (eg int )  control flow – switch, foreach  functions  ref-out parameters  no global functions, by default not virtual  const – but only for simple types and string  operators  always public, always static  compound assignment, ++, families  conversions – implicit and explicit  get and set { accessors }  instance indexers [ ] [ , ]  instance and static properties
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×