TP

C# for Java Programmers Flashcards

Keywords from Java reused in C

  • Control flow: if, else, do, while, for, switch, case, default, break, continue, try, catch, finally, throw
  • Operators: ., (), [], */%, +-, <, ==, &&, ||, =
  • Primitive types: bool (true, false), byte, char, int, long, float, double
  • Classes and objects: class, interface, abstract, static, volatile, new, null, this
  • Methods: public, private, protected, void, return

Keywords from Java changed in C

  • extends, implements :
  • super base
  • final readonly, sealed
  • import using
  • package namespace {...}
  • instanceof is
  • synchronized lock x
  • finalize() ~ClassName() (clean-up called by garbage collector)

C# Enhancements

  • Generics: C# List<T> uses a !0[] array, avoiding type erasure and casting, unlike Java's ArrayList<T> which uses Object[].
  • Switch with strings: Supported directly in C#.
  • Autoboxing/Autounboxing: Not needed in C#.
  • Try-with-resources: C# uses the using statement.
  • Enumerated types: Supported in C#.
  • Enhanced for loop: C# uses the foreach loop.
  • Varargs: C# uses the params keyword.
  • Static imports: C# uses using extension methods.
  • Lambda expressions: Supported in C#.

Examples of C# Enhancements

  • Using Statement:
    csharp using (FileStream fs = File.OpenRead(path)) using (StreamReader sr = new StreamReader(fs)) { string line; while ((line = sr.ReadLine()) != null) { Console.WriteLine(line); } }
  • Enum Definition and Usage:
    csharp enum TrafficLightColour {Red, RedAmber, Green, Amber}; TrafficLightColour tlc = TrafficLightColour.Red;
  • Foreach Loop:
    csharp string[] presidents = new string[] { “Washington”, “Jefferson”, “Lincoln”, “Roosevelt” }; foreach (string president in presidents) { Console.WriteLine(president); }
  • Params Keyword:
    csharp public static void SumList(params int[] list)
  • Lambda Expressions:
    csharp int[] somevalues = { 10, 20, 5, 2, 40, 1 }; int numberOfLargeValues = somevalues.Count(x => x >10);

Differences in Control Flow

  • Each non-empty case in a switch statement must end with a break statement (or return, goto, throw).
  • goto can be used to jump out of a nested for loop.
  • No checked exceptions (no throws list on method declarations).
  • Exception handling is less rigid.
  • An expression or a block can be checked using the checked keyword to throw a System.OverflowException if an overflow occurs.
    • Example:
      csharp int x = 1000000; int y = checked(x*x);

Switch Statement for a Finite State Machine

int state = 0; // begins in state 0
int ch = Console.Read(); // reads first transition symbol
switch (state)
{
    case 0:
        if (ch=='a') {ch = Console.Read(); goto case 1;} 
        else if (ch=='c') goto case 2;
        else goto default;
    case 1:
        if (ch=='b') {ch = Console.Read(); goto case 1;}
        else if (ch=='c') goto case 2;
        else goto default;
    case 2:
        Console.WriteLine(“Input valid!”); break;
    default:
        Console.WriteLine(“Illegal character: “ + (char) ch); break;
}

Differences in Types

  • Unsigned types: byte, ushort, uint, ulong (for systems programming).
  • decimal type: For large decimal numbers with high accuracy (financial mathematics).
  • Uniform Type System (UTS): All types inherit from System.Object.
    • Can have a List<int> and insert int without boxing.
  • Managed pointers: &T is the type of a managed pointer to T.
    • int& i means CLR will check at runtime that i is pointing to an int (type-safe).
  • Unmanaged pointers: *T is the type of an unmanaged pointer to T.
    • int* i means CLR will not do such checks, and arithmetic operations are possible (only in unsafe blocks).

Structs

  • Lightweight objects for holding temporary data.

  • Held on the stack (no garbage collection).

  • Value types: copying has value semantics.

    • Copy p to q and change q, then p won’t change.
  • Objects are reference types: copying has reference semantics.

    • Copy p to q and change q, then p will also change.
  • Example:

    struct Point {
        public int x, y; // fields
        public Point(int x, int y) {this.x = x; this.y = y;}
        public void MoveTo(int x, int y) {this.x = x; this.y = y;}
    }
    
    Point q = p; // How to copy Point p to q
    

Block Matrices

  • Java represents matrices as arrays of arrays (can be jagged).
  • C# allows block matrices of uniform dimensions.
  • Examples:
    csharp int[,] a = new int[2,3]; int[,] b = {{1, 2, 3}, {4, 5, 6}}; int[,,] c = new int[2,4,2];

Dynamic Typing

  • Designed to support dynamically typed languages (e.g., IronPython).
  • Defers binding and dispatch operations to runtime.
  • Example:
    csharp dynamic s = GetObject(); Console.WriteLine(s.ToUpper()); // object s doesn’t work
  • Do not confuse with var, where the type is inferred statically.
  • Example:
    csharp var numbers = new List<int>();

Properties

  • No need to write type signatures for getters and setters.

  • Can use the record syntax to “invisibly” call them both.

  • Example:

    class Person {
        private string name; // field
        public string Name { // property
            get {return name;}
            set {name = value;} // often omitted
        }
    }
    
    Person p = new Person();
    p.Name = “Ian”;
    Console.WriteLine(p.Name);
    

Auto-implemented Properties (C# 3.0+)

  • If getters and setters are trivial, C# can derive them.
  • The same class with auto-implemented properties:
    csharp class Person { public string Name { get; set; } }

Indexers

  • Properties that can be indexed, i.e., accessed like an array.
  • Implemented as an invisible property Item.
  • Example:
    csharp class Vector { private int x, y, z; public Vector (int x, int y, int z) { this.x=x; this.y=y; this.z=z; } public int this[int index] { // Indexer declaration get { // e.g., v[2] if v has type Vector if (index == 0) return x; else if (index == 1) return y; else if (index == 2) return z; else throw new ArgumentOutOfRangeException(); } // setter omitted to save space, uses value as before } }

Reference Parameters

  • In Java, all parameter passing is by value.

  • In C#, using the ref keyword, passing can be by reference.

    • The reference parameter represents the same storage location as the variable given as the actual parameter.
  • Using the out keyword, the variable need not be assigned first.

  • Example:

    static void Swap(ref int x, ref int y) {
        int temp = x;
        x = y;
        y = temp;
    }
    
    static void Main() {
        int i = 1, j = 2;
        Swap(ref i, ref j); // now i = 2, j = 1
    }
    

Modifiers: new and override

  • If a method in a subclass shares its name with a method in a base class, this will cause a warning.

  • Use new or override to indicate that this is intentional.

  • override indicates that the new method is a replacement.

  • new indicates that the old method should still exist but be hidden.

  • Example:

    public class BaseC {
        public int x;
        public void Invoke() { }
    }
    
    public class DerivedC : BaseC {
        new public void Invoke() { }
    }
    

Using yield return for Lazy Evaluation

  • Example:

    public class PowersOf2 {
        static void Main() {
            foreach (int i in Power(2, 8)) {
                Console.Write("{0} ", i);
            }
        }
    public static System.Collections.Generic.IEnumerable&lt;int&gt; Power(int number, int exponent) {
        int result = 1;
        for (int i = 0; i &lt; exponent; i++) {
            result = result * number;
            yield return result;
        }
        // returns number^0 ... number^(exponent-1)
    }
    
    }

LINQ (=Language Integrated Query)

  • Lazy evaluation used to implement LINQ.
  • Like SQL but from arrays, data structures, XML documents, etc.
  • Example (preferred standard syntax):
    csharp var results = from c in SomeCollection where c.SomeProperty < 10 select new {c.SomeProperty, c.OtherProperty};
  • The pair returned is an instance of an anonymous type.
  • LINQ in a more informative but awkward syntax:
    csharp var results = SomeCollection .Where(c => c.SomeProperty < 10) .Select(c => new {c.SomeProperty, c.OtherProperty});

Using Delegates (like Command Pattern)

  • Example:

    delegate int BinOp(int a, int b); // BinOp is now a class providing an Invoke method
    
    static class DelegateExample {
        static int Add (int a, int b) { return a+b; }
        static void Main() {
            BinOp add = new BinOp(Add);
            int three = add(1,2); // called the Invoke method on the BinOp object
        }
    }
    

Reading Material

  • C# in Depth Jon Skeet 2019
  • .NET Application Development Hanspeter Mössenböck et al
  • msdn.microsoft.com (see Moodle links)
  • practice, practice, practice