‹header›
‹date/time›
Click to edit Master text styles
Second level
Third level
Fourth level
Fifth level
‹footer›
Page ‹#›
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.
The string type in C# is very similar to the String class in Java. Just as in Java a string is an immutable reference type.
Unlike in Java, you can use the subscript notation to access the characters of a string in a readonly context. In other words the string class in C# has an indexer with return type char, an int parameter, and a get (but no set) accessor:
... class String
    {
        public char this [ int index ]
        {
            get { ... }
        }
    }
Note that the String class
• is sealed; it cannot be derived from.
• contains an indexer with a get but no set accessor
• contains a Length property with a get but no set accessor
The StringBuilder class in C# lives in the System.Text namespace and is very similar to the class of the same name in Java. The StringBuilder class is used for creating strings. If you are creating a string in a number of steps (perhaps by a sequence of appends) it is more efficient to create the string with a StringBuilder because of the immutable nature of the string class. You can thing of StringBuilder as a mutable version of string:
• it contains an indexer with a get and set accessor
• it contains a Length property with a get and set accessor
Example of use:
static string SuperCat(params string[] strings) {
    StringBuilder builder = new StringBuilder();
    foreach (string s in strings) {
        builder.Append(s);
    }
    return builder.ToString();
}
static void Main() {
    Console.WriteLine(SuperCat("a", "b", "c"));
}
Inside a verbatim string literal the characters are treated verbatim. This means escape sequences are not interpreted and neither are carriage returns. Verbatim string literals are very useful for expressing regular expressions.
A static readonly field can be passed as a ref parameter in a static constructor.
A static readonly field can be passed as a out parameter in a static constructor.
Consider what happens if you pass a reference variable as an out parameter when the reference variable is definitely assigned:
    static void Main()
    {
         ClassType var = new ClassType();
        Argument(out var);
    }
The method receiving the out argument must reassigned it since it is an out argument. The fact that the argument is already assigned is of no consequence to the method: the method cannot inspect the out argument in any way until it assigns to it which it must do. In other words an out argument cannot pass information into the method, and by contrast, an out parameter must always pass information out of the method (even if it just assign to null).
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
default initialised.
bool to false
integral types to 0
floating point types (including decimal) to 0.0
enum types to 0
reference types (including arrays) to null
Note that in Java an initialisation via new int[4] or via {1,2,3,4} are individually legal, but illegal in combination:
    int[] row = new int[4]{1,2,3,4}; // illegal Java
In C# initialisers may not be omitted (they can be in C++)
    // both of these are illegal C#
    int[] row = new int[4]{1,2,3};
    int[,] grid = new int[2,3]{ {1,2,3}, {4,5} };
The array size may be completely omitted. For example:
    int[] row = new int[]{1,2,3,4}; // legal
    int[,] grid = new int[,]{{1,2},{3,4}}; // legal
The new expression may be dropped if the initialisers are specified. This is asyntactic convenience; underneath the new expression still happens.
    int[] row = {1,2,3,4}; // legal
Note that an array creation expression is a legal expression in its own right:
    Func(new[]{1,2,3,4});
Note that the array initialisation syntax applies only to true arrays and not to the System.Array class that all C# arrays inherit from:
    System.Array grid = new int[]{1,2,3,4}; // illegal
When you initialise an array instance, for example:
    int[,] cosmic = { {1,2,3}, {4,5,6} };
the IL code contains a single instruction to set each array element.
If you want to make rowLength and colLength constant within the Use function the best you can do is as follows:
struct constInt
{
    public constInt(int value)
    {
        this.value = value;
    }
    public static implicit operator int ( constInt arg )
    {
        return arg.value;
    }
    private readonly int value;
}
static void Use(int[,] grid)
{
    constInt rowLength = new constInt(grid.GetLength(0));
    constInt colLength = new constInt(grid.GetLength(1));
    ...
}
C#, like Java, also supports ragged arrays. A ragged array is an array of arrays. Since in C# an array is a reference type, an array of arrays is actually an array of references, where each reference refers to its own array. Because of this the elements of the whole "top level" array can be scattered throughout the heap. This is in contrast to rectangular (also called multidimensional) arrays where there is a single contiguous block of heap memory.
There is only one syntax for declaring a ragged array in C#.
    int[] ragged[]; // illegal C#, legal Java
    int[][] ragged; // legal in both
The elements of the newly created array are defaulted initialised just as with a rectangular array. For a ragged array the top level array elements are always array which are reference types, so they always default to null.
To initialise a ragged array variable you use the a new expression as before. When you do this you can only specify the size of the first dimension. The following would be legal in Java (but would not create a rectangular array of length 12; Java does not support rectangular arrays) but is illegal in C#:
    int[][] ragged = new int[3][4];
The shorthand of using {1,2,3,4} instead of new int[4]{1,2,3,4} does not work for an "inner" ragged array initialiser. Hence the following is illegal:
    int[][] ragged = new int[3][] {
        int int[2],
        null,
        { 1,2,3,4 }
    };
The shorthand can only be used on the top level for ragged array initialisation:
int[][] ragged = {
    int int[2],
    null,
    { 1,2,3,4 }
};
Console.WriteLine(params object[] objects);
is very useful and there is no counterpart in Java's System.out.println(...);
C# allows memory to be directly manipulated but only within blocks of code marked unsafe. C# allows single statements, blocks, methods, and classes to be marked as unsafe. Within unsafe code you can use pointers. Pointers can be useful for: • interoperability with C API's. Note however that an unmanaged C# function can be faster than calling an external C function (via the extern keyword) since an extern function has to leave the managed environment (which takes time) and an unsafe C# function does not.
• accessing memory outside the managed (garbage collected) heap
• performance critical hotspots
The stackalloc keyword,as its name suggests, allocates a block of memory on the stack. This means that the lifetime of the allocated block is tied to the containing function. The allocated block can use [ ] like notation but is afforded none of the benefits of genuine managed array: no meta-information, no bounds checking. If unsafe code requires a pointer to a managed object, the object must first be pinned. This is because in a mangaed environment, objects are garbage collected. Garbage collection is a complicated process which involves relocating objects to reduce fragmentation. Clearly if an unsafe pointer pointed to an area of memory where an object used to exist, but no longer does (having been relocated by the garbage collector) then all bets would be off. The fixed statement allows an object to be temporarily pinned to prevent it from being relocated.
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.
mind your P's and Qs'.
Target type of cast must be exact. Conversions are not considered.
The System.Object class (aka object) contains three public virtual methods. These will be familiar to Java programmers. By default the ToString method returns the name of the class/struct. It can be overriden in derived classes/structs to return a more specific representation of the object/value. ToString is particularly useful for debugging. It is also possible to take complete control of formatting via the IFormattable interface (in exactly the same way that it isn't for printf). The Equals method is used to determine if two objects have the same contents. It is used by the collection classes such as Array and HashTable. Two objects that are the same by Equals are required to return the same hashcode value from GetHashCode. However, the default implementation of GetHashCode doesn't fulfil this requirement. You must therefore override it to work correctly.
A struct cannot inherit from a struct or class except of course that a struct implicitly derives from System.Object.
Note that a struct implicitly inherit from the System.Object class which does have a public default constructor. However a struct can never call this base class constructor explicitly in code:
    struct CantDoThis
    {
        public CantDoThis()
            : base() // compile time error
        {
            ...
        }
        ...
    }
An override method is declared using the override keyword. An override method specialises an existing inherited virtual method (with an identical signature and accessibility). The existing method must be virtual. In other words the existing method (that is being overriden) must be declared with the abstract, virtual, or override keyword. An override method is implicitly virtual and cannot be declared in combination with the virtual keyword. An override method cannot, in general, be declared in a struct. However, there are three exceptions. System.Object declares three public virtual methods: Equals, GetHashCode, and ToString. The System.ValueType class overrides these three virtual methods. All user-defined structs implicitly inherit from System.ValueType. Hence a user-defined struct can override the implementation of these three methods that it inherits from System.ValueType with implementations of its own. Note that if System.ValueType implements any protected virtual/override methods, they cannot be overriden in a user-defined struct since a struct cannot declare protected methods.
All methods of a struct are implicitly sealed and can never explicitly use the sealed keyword, even in combination with the override keyword.
The sealed modifier is always used in combination with the override modifier:
...
The sealed modifier can be used to declare the final implementation of an inherited virtual method:
...
The sealed modifier can be used to declare the final implementaiton of an inherited override method:
...
The sealed modifier can be used to declare the final implementation of an abstract method:
...
The override keyword can only be used on a struct method when overriding public virtual methods in System.ValueType. The new keyword can redundantly be used on struct methods that do not hide any methods from System.ValueType. The new keyword is only required when defining new methods that hide methods from System.ValueType.
Java interfaces are allowed to redundantly specify the public access modifier. Java interfaces are also allowed to contain static fields.
Why are they private-ish...
interface IFirst
{
    void M();
}
interface ISecond : IFirst
{
    new void M();
}
class Third : ISecond
{
    void IFirst.M() {...}
    void ISecond.M() {...}
}
In Java you make a public method the implementation of a protected abstract method.
A sealed class cannot also be an abstract class.
Sealed classes prevent derivation and also enable certain runtime optimisations by transforming a virtual method call on a sealed class into a non-virtual method call.
A sealed class can declare a protected method. This seems counter-intuitive since a sealed class cannot have any derived classes. However, the sealed class might inherit from an abstract class that declared a protected abstract method. In this case the sealed class must declare an implementation of the protected method.
Only an abstract class can declare an abstract method.
A sealed class cannot declare a method with the virtual modifier. This is because the virtual modifier specifies the first implementation of a method. Since a sealed class cannot be derived from there is no chance of declaring another specialised override version.
1.an abstract class is allowed to override an inherited virtual or override method (that is, a method with an implementation) with an abstract method, a method without an implementation. This can be useful if you wish to force any further derived classes to reimplement the method.
2.an abstract class is allowed to inherit from a class. The abstract class may wish to declare an abstract method that hides an inherited method of the same name.
3.by default a new method is not virtual but can be declared so if wished.
4.a sealed override method overrides an identical inherited virtual method and stops any further overriding of the method in further derived classes. The sealed modifier can only be used in combination with the override modifier.
You cannot use a break statementy to exit a finally block.
You cannot use a continue statement to exit a finally block.
You cannot use a goto statement to exit a finally block.
You cannot use a return statement to exit a finally block (you can in Java and it drops the pending exception!)
There is a sixth access modifier, protected and internal, but this is only accessible from IL.
params are allowed as part of the signature.
params are allowed as part of the signature.
params are allowed as part of the signature.
params are allowed as part of the signature.
params are allowed as part of the signature.