|
|
|
|
|
|
|
overview |
|
built-in value types |
|
enums |
|
parameters |
|
control flow |
|
structs |
|
constructors |
|
fields |
|
operators |
|
indexers |
|
properties |
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
C# programs are constructed from tokens |
|
|
|
|
five kinds of tokens in C# programs |
|
|
|
|
|
C# has a sensibly limited
"preprocessor" |
|
no #include, no #pragma |
|
#define, but no macros |
|
|
|
|
|
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 |
|
|
|
|
some identifiers have a fixed meaning |
|
|
|
|
|
|
some tokens represent fixed values |
|
|
|
|
some tokens represent fixed actions |
|
|
|
|
|
some tokens group or separate |
|
{ and } form scoped blocks |
|
semi-colons mark the end of a simple statement |
|
|
|
|
|
declarations introduce variables into a scope |
|
a variable has an identifier and a type |
|
a variable's type can never change |
|
|
|
|
|
expressions compute things! |
|
an expression yields a value |
|
an expression must also have a side- effect |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
bool is a keyword |
|
an alias for System.Boolean |
|
only values are true and false |
|
|
|
|
|
|
|
|
|
no implicit conversions to bool |
|
ever |
|
none |
|
nada |
|
zip |
|
under any circumstances whatsoever |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
operands are evaluated strictly left to right |
|
same as in Java, unspecified in C++ |
|
|
|
|
|
DivideByZeroException, OverflowException |
|
un/checked expressions |
|
un/checked { statementsopt } |
|
|
|
|
|
integer MSIL instructions come in two forms |
|
one checks for overflow ( eg mul.ovf ) |
|
one doesn' t check for overflow ( eg mul ) |
|
|
|
|
|
never throw exceptions |
|
(u)int shift à count & 0x1F |
|
(u)long shift à count & 0x3F |
|
|
|
|
|
implicit, widening conversions |
|
never lose information, never throw exception |
|
explicit narrowing conversions (casts) |
|
may lose information, may throw exception |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
a user- declared value- type |
|
|
|
|
|
|
enums implicitly derive from System.Enum |
|
|
|
|
enum variables can mostly be used as ints |
|
|
|
|
|
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 |
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
a plain parameter is a copy of the argument |
|
no frills bitwise copy |
|
the argument must be definitely assigned |
|
argument can be an "rvalue" |
|
|
|
|
|
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 |
|
|
|
|
|
an out parameter is an alias for the argument |
|
no copy takes places |
|
argument need no t be definitely assigned |
|
parameter must be definitely assigned |
|
argument must be an "lvalue" |
|
out required on argument and parameter |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
a block and its parent block |
|
cannot have a variable with the same name |
|
sibling blocks |
|
can have variables with the same name |
|
|
|
|
|
no built-in conversions to/from bool |
|
System.Convert .ToBoolean(int i) exists though |
|
definite assignment consequences |
|
just like in Java |
|
|
|
|
|
usual syntax |
|
switch on integral types |
|
case labels must be compile time constants |
|
etc |
|
|
|
|
|
unusual syntax |
|
you can switch on a string |
|
fall through is illegal, even on default clause |
|
you can goto a case/default label ! |
|
|
|
|
standard Java,C++ like syntax |
|
|
|
|
|
for statement |
|
declared variables are scoped to for statement |
|
|
|
|
|
from shell, VB, PERL, etc |
|
works on any collection, including [ ] arrays |
|
|
|
|
|
|
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 |
|
|
|
|
|
|
no labelled break statement |
|
|
|
|
|
|
a user- defined value- type |
|
|
|
|
|
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 |
|
|
|
|
|
usual dot operator to access field |
|
field must be assigned before its value is used |
|
default c'tor default initialises fields zero/false/null |
|
|
|
|
|
unusual rules |
|
compiler declares default c'tor |
|
you cannot declare the default c'tor |
|
default c'tor zero-initialises all instance
fields |
|
|
|
|
|
a c' tor can call a sibling c' tor |
|
syntax is similar to C++ |
|
no general member-init-list syntax though |
|
|
|
|
|
instance fields... |
|
are default initialised in compilers default
c'tor |
|
must be explicitly initialised in users c'tor |
|
|
|
|
|
readonly instance fields... |
|
are instance fields that cannot be assigned to |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
you can declare a "copy constructor" |
|
it is not called for value parameters/returns |
|
a copy is always a plain bitwise copy |
|
|
|
|
|
you cannot overload simple assignment |
|
a copy is always a plain bitwise copy |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
operators are always defined as |
|
public static methods (never virtual) |
|
copy parameters only (not ref-out ) |
|
one+ parameter must be of containing type |
|
|
|
|
you can't overload assignment, but this... |
|
|
|
|
|
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 |
|
|
|
|
|
some operators have natural partners |
|
you can't have one without the other |
|
|
|
|
|
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
& | |
|
|
|
|
|
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 |
|
|
|
|
"readonly" local variable |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
indexers provide [ ] like syntax of use |
|
always an instance member, can be virtual |
|
no ref-out parameters |
|
can be overloaded |
|
|
|
|
|
indexers can only contain accessors |
|
get { accessor } for read context |
|
set { accessor } for write context |
|
|
|
|
|
an indexer with no set accessor |
|
is a read-only indexer |
|
and indexer with no get accessor |
|
is a write-only indexer |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
an object oriented smart field |
|
get and set accessors |
|
instance property can be virtual |
|
|
|
|
|
properties can be static |
|
unlike indexers |
|
|
|
|
|
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 |
|
|
|
|
|
.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 |
|