CE303 Lecture 1
Main Tools
Java, C#, Haskell
We’re not going to go “deep” in C# and Haskell
The idea is to expose you to different languages and paradigms
For C#, you’re responsible to demonstrate that you can learn by independent reading, as it would be the case in the workplace
Java is still the “main” language for this module
IntelliJ, Visual Studio Code
You can download these for free. I have put the VS code link on Moodle in unit 1. Currently c# is not working in the labs. The School is preparing a lab image for those working from home.
1
Lecture 1
Introduction to C#; C# vs Java;
.NET Framework
2
PART I
Microsoft .NET Framework
In 2000, Microsoft released .NET Framework – designed to support multiple languages and an improvement over the Java model
The default language for .NET Framework is C#
https://code.visualstudio.com/docs/languages/csharp#_installing-c35-support
4
What are the differences between
.NET and Java?
At the first glance, not so many
Conceptually, .NET is a little closer to low-level programming
.NET has more tools for writing fast code
.NET fixes some weaknesses of Java but it still has its own weaknesses
We will learn some of the differences later in this module
From now on, when talking about .NET, we will mostly focus on C# but remember that C# is just a high-level language that gives access to most of the functionality of .NET Framework
Java vs C#
A quick overview of a few differences
Vocabulary
(Non-static) field = instance variable = attribute
Method = function
Base class = parent class
Child class = subclass
Value type = primitive type
Reference type = non-primitive type
Primitive vs non-primitive types in Java
Java has primitive and non-primitive types
Primitive types: int, boolean, double…
A variable of a primitive type stores a value
Non-primitive: String, int[], Integer, any object…
A variable of a non-primitive type stores a reference to a value
Object is a superclass of any non-primitive type
int x = 56;
Integer x = 56;
56
56
Value types vs reference types in C#
The idea is similar in C#: int, bool, double are value types
Arrays, strings and objects are reference types; Object is a superclass (base class) of any reference type
Difference 1: C# supports user-defined value types such as structs
Difference 2: In C#, value types also inherit from Object
You can write 45.ToString()
Difference 3: As a result, in C#, a variable of a value type can be treated as a reference-type variable; this is called boxing
Java also has boxing/unboxing
Why user-defined value types matter?
The short answer is performance
Imagine you need an array of points, each point containing two coordinates
X = 4, Y = 1
Java
class Point {public int X, Y;}
…
Point[] points;
C#
struct Point {public int X, Y;}
…
Point[] points;
X = 0, Y = 0
X = 5, Y = 5
points:
points:
X = 4, Y = 1
X = 0, Y = 0
X = 5, Y = 5
Note that in Java we have a reference to array cells, and each cell is a separate reference to coordinates. In C#, we only have the reference to array cells.
10
Getters and setters
In Java, it is common to provide getters and setters in a class to give access to a field:
class Point
{
private int x, y;
public int getX() { return x; }
public int getY() { return y; }
public void setX(int value) { x = value; }
public void setY(int value) { y = value; }
}
Getters and setters
Advantages:
You can make a read-only field (no setter available)
You are (potentially) informed about every modification of the field
You can restrict how the field is modified (e.g., reject all attempt to set x to a negative value)
Disadvantages
Clatter the code
Properties in C#
Properties give all the advantages of getters and setters but require less code and behave like fields from outside
class Point
{
private int x, y;
public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
}
OR
Point point = new Point();
point.X = 5;
Console.WriteLine(point.X);
class Point
{
public int X { get; set; }
public int Y { get; set; }
}
Call-by-value
What is the output of this C# program?
void MyFunction(int x)
{
x = 10;
}
void Main()
{
int x = 5;
MyFunction(x);
Console.WriteLine(x);
}
Call-by-value
Whenever you call a function in Java or C#, the values of the variables passed as parameters are copied
The function MyFunction modifies not the value of the variable x defined in the Main function, but the value of a copy of x
Changes to the function parameters do not affect the variables passed to that function; the output will be “5”
Call-by-reference
Idea: If you pass not the value of a variable but a reference to that variable then the changes inside the function will affect the value of the passed variable
In C# (Java does not have call-by-reference), you can request that a function parameter is passed by reference:
void MyFunction(ref int item)
{
item = item – 10;
}
void Main()
{
int x = 20;
MyFunction(ref x);
Console.WriteLine(x);
}
Call-by-reference
The output of this program will be “10” because you pass not the value but a reference to variable x
The keyword ref has to be used both when you declare the variable and when you call the function
Effectively, the ref parameters pass data in both directions: in and out of the function
For ref I have to have initialised a value prior to the function call, as ref is for passing data both in and out of the function.
If you want to pass the data only out of the function, you can use keyword out; the compiler will make sure that the function does not use the value of the passed variable
For out I don’t need to have initialised a value when I’m doing the function call, as out is only for passing data out of the function.
Java does not support call-by-reference
17
Call-by-reference example with out
void MyFunction(out int item)
{
item = 10;
//item = item – 5 would be invalid
}
void Main()
{
int x = 5;
MyFunction(out x);
Console.WriteLine(x);
}
It’d be invalid because we are using “out”, so we cannot pass a value in as an argument. We are only passing values OUT.
18
Enums
Both Java and C# support enumerations (enums)
Enumeration is a user-defined type for a fixed set of constants; the basic syntax is identical:
Enums are type-safe and for that reason better than integer constants
In C#, enums are user-defined value types closely linked to integers
E.g., (int)Weekday.Wed is 2 (indexing starts with 0)
and (Weekday)2 is Weekday.Wed
In Java, enums are non-primitive (reference) types
public enum Weekday { Mon, Tue, Wed, Thu, Fri, Sat, Sun }
Handling enums
Find out the “index” of a enum constant:
C#: (int)Weekday.Wed
Java: Weekday.Wed.ordinal()
Find out the name of the constant
Weekday.Wed.ToString() (toString() in Java)
Convert a string into the enum value:
C#: Enum.TryParse()
Java: Weekday.valueOf()
Get an array of all the enum values:
C#: Enum.GetValues(typeof(Weekday))
Java: Weekday.values()
Etc.
20
Examples: NORTH, SOUTH, EAST, WEST; HEART; SPADES; … ACE KING QUEEN …
Proper type is Enum
Has a protected constructor Enum(String name, int ordinal);
valueOf(Size.class, “MEDIUM”);
Beyond simple enum in Java
Since enum is a reference type in Java, the enum body can define methods and fields
If fields are defined, then each enum constant needs to be given field values in a constructor
enum Size {
SMALL(“S”), MEDIUM(“M”), LARGE(“L”);
private String abbreviation;
private Size(String abbreviation) {
this.abbreviation = abbreviation; }
public String getAbbreviation() {
return abbreviation; }
}
21
Since I defined a String abbreviation as a field of enum Size, then the respective constants SMALL, MEDIUM, LARGE need to be given field (String) values.
END OF PART I
PART II
Abstract classes
Interfaces
Default and static methods (Java)
Inheritance
Functional interfaces (Java)
Delegates (C#)
Abstract (Java and C#)
A method (also property in C#) can be marked as abstract to indicate that the method has to be overridden in child classes
Any class that contains abstract members (defined within the class itself or abstract methods inherited from the parent class) has to be marked as abstract
Abstract class can contain non-abstract methods
An abstract class cannot be instantiated – you cannot create objects belonging to such a class
Interfaces
An interface can be seen as a contract on classes
A class that implements the interface must comply with the contract
A class can implement more than one interface
Both Java and C#
Interfaces are types, but they are not classes
They cannot be instantiated
Interface defines method signatures (= implicitly abstract); every class that implements an interface has to implement its (abstract) methods
25
Interfaces in C#
public interface IComparable
{
int CompareTo(T other);
}
public class Circle : IComparable
{
private int x, y;
private int radius;
public int CompareTo(Circle other)
{
return radius.CompareTo(other.radius);
}
}
…
Array.Sort(circles);
Interfaces in C#
The convention is to start the name of an interface with ‘I’
IComparable
The Circle class could potentially inherit from some other class and at the same time implement IComparable:
public class Circle : Shape, IComparable
Array.Sort uses the CompareTo method to compare the elements of the array and order them accordingly
Interfaces in Java
Java interfaces are similar to interfaces in C#
In addition, Java interfaces can contain
Constants
Default methods (since Java 8)
Static methods (since Java 8)
Default Methods in Interfaces (Java)
Since Java 8, you can define default methods in interfaces
These methods are NOT abstract, they come with an implementation
Default methods do not have to be implemented in classes that implement an interface
Although they can be overridden if desired
Why does anyone need them?
You can evolve an interface by adding further “default methods” to it without forcing an update of all of the existing classes that implement the interface
This has made it possible to retrofit additional methods to standard API interfaces (like Collection or Comparator) without breaking backward compatibility (i.e. without having to go and override all these new default methods in classes that implement the relevant interface)
Default Methods: Comparator Example
interface Comparator
int compare(T o1, T o2);
…
// Returns a comparator that imposes the reverse
// ordering of this comparator.
default Comparator
// Returns a lexicographic-order comparator
// with another comparator.
default Comparator
Comparator super T> other)
…
}
Default methods: conflict resolution
If a class inherits several implementations of a method with the same name, we could have multiple inheritance conflicts
How are they resolved?
Inheritance from a class has priority over inheritance from an interface
Derived interfaces or sub-interfaces take higher precedence than the interfaces higher-up in the inheritance hierarchy
If you code a new class that implements different interfaces which share the same method, and it is declared as default in at least one of them, then the method has to be explicitly overridden in the new class
31
Multiple inheritance problem
From: https://beginnersbook.com/2017/10/java-8-interface-changes-default-method-and-static-method/
32
Multiple inheritance problem:
how to resolve
From: https://beginnersbook.com/2017/10/java-8-interface-changes-default-method-and-static-method/
33
static methods in interfaces (Java)
Java interfaces can also contain static methods
Similar to default methods
But since they are static, we cannot override them in the implementation classes
Having static methods in interfaces does not create a multiple inheritance problem
Functional interfaces (Java)
Sometimes you may want to define a reference to a method; for example, you may want to pass a method to another method
In Java, the best we can do about this is to use a functional interface, i.e. interface with a single abstract method (SAM)
Below we define type MyPredicate as a reference to a method that takes one int parameter and returns a boolean:
interface MyPredicate
{
boolean apply(int value);
}
Functional interfaces (Java)
Then we define a class implementing MyPredicate:
class SelectPositive implements MyPredicate
{
@Override
public boolean apply(int value) {
return value > 0;
}
}
We define another method taking a method of this form as an argument
void printSelected(int[] list, MyPredicate select){
for (int i = 0; i < list.length; i++)
if (select.apply(list[i]))
System.out.println(list[i]);
}
Functional interfaces (Java)
Lastly, we simply have to call printSelected
printSelected(list, new SelectPositive());
Functional intefaces (Java)
java.util.function package defines various general functional interfaces
Function
UnaryOperator
Consumer
And lots of specialisations for primitive types like
IntToDoubleFunction, ToDoubleBiFunction, DoublePredicate, IntBinaryOperator, LongConsumer, …
Having these specialisations improves efficiency, but it is rather ugly to have 40+ different interface definitions!
Delegates (C#)
C# has a special mechanism for defining a reference to a method called delegates
As with Java, we define type MyPredicate as a reference to a method that takes one int parameter and returns bool:
public delegate bool MyPredicate(int value);
Delegates (C#): full example
public delegate bool MyPredicate(int value);
bool SelectPositive(int value)
{
return value > 0;
}
void PrintSelected(int[] list, MyPredicate select)
{
for (int i = 0; i < list.Length; i++)
if (select(list[i]))
Console.WriteLine(list[i]);
}
...
PrintSelected(list, SelectPositive);
Standard delegates (C#)
.NET Framework includes a lot of generic delegates
Action takes no parameters and does not return anything
Predicate takes no parameters and returns bool
Func
Each of these delegates has versions that take parameters, e.g.
Action
Func
Note that delegates can store references to both instance and static methods
41
END OF PART II
PART III
String interpolation (C#)
Exceptions
Unit testing
String interpolation (C#)
String interpolation is a mechanism for constructing strings
Example:
string name = “Daniel”;
int age = 50;
string s = $”Name: {name}; Age: {age}”;
Note that the string is prefixed with ‘$’
Formatting options:
string s = $”Age: {age,10:0.00}”;
will produce “Age: 50.00”
This has the same functionality with string concatenation, but has better memory usage.
44
Exceptions (Java)
Exceptions are for dealing with exceptional (“error”) states
String name = null;
int n = name.length(); // ERROR
It is the Java Virtual Machine (JVM) that throws an exception. Unless there is a corresponding handler, the program will exit with a stack trace:
Exception in thread “main” java.lang.NullPointerException
at Greeter.sayHello(Greeter.java:25)
at GreeterTest.main(GreeterTest.java:6)
45
Checked and Unchecked Exceptions (Java)
The Java compiler tracks only checked exceptions. Examples:
IOException is checked
NullPointerException is unchecked.
In general, checked exceptions are thrown for reasons beyond the programmer’s control, like non-existing files or other resources missing
Checked exceptions must be
declared in the method header
or caught
You can even declare exceptions for method main()
Unchecked exceptions clutter the code less, but they are easier to overlook
46
Unchecked are: RuntimeException, Error and their subclasses
Exceptions in C#
C# does not distinguish between checked and unchecked exceptions
In C#, you do not declare method exceptions, however you will usually see the list of possible exceptions in the method documentation
Otherwise C# exceptions are very similar to Java exceptions
Unit Testing
Testing a unit of code in isolation
not the whole application
typically a method or a class
carried out by developers and not by end-users.
Advantage: easier to test an isolated piece of code, also makes later integration easier.
Relies on test data that describes the correct behaviour of the unit.
Traditionally, test data is generated manually
But there are interesting new approaches for automated generation of random test inputs.
JUnit
Popular framework for Java unit testing
For detailed information see: www.junit.org
There are extensions to help with testing of web applications (HttpUnit, jWebUnit)
Integrated into IDEs such as IntelliJ and Eclipse
And into build tools for performing tests during the build process.
JUnit philosophy: whenever you implement a class, also
write a companion test class
Testing with JUnit
Annotate test methods with @Test
Check correctness with assertions:
call assertTrue on a boolean expression in test method
or other methods like assertEquals, assertNull, …
You can also specify that a method should throw an exception
To run some code before/after each test
@Before, @After
To run some methods before/ after all the tests in one class:
@BeforeClass, @AfterClass
The execution order of JUnit tests in one class is unspecified.
Do NOT confuse assert (Java keyword) and assertTrue(JUnit)
51
public class Calculation {
public static int findMax(int arr[]){
int max=0;
for(int i=1;i
}
}
Now we can define another method that takes a method of this form as a parameter
void PrintSelected(int[] list, MyPredicate select){
for (int i = 0; i < list.length; i++)
if (select.apply(list[i]))
System.out.println(list[i]);
}
Functional interfaces (Java)
To call the method, we simply write
printSelected(list, new SelectPositive());
This is a lot of code to write for a very simple concept
Java supports anonymous classes but they still require quite a lot of hard-to-read code for a simple task
Instead, you can use a lambda expression
PrintSelected(list, x -> x > 0);
With lambda expressions, you do *not* have to implement the Interface (public class X implements MyInterface); so you skip that implementation, and also the interface’s method implementation. Instead, you just put the method definition as a lambda expression.
60
Lambda Expression Syntax
Parameter List
(int x, int y)
Arrow Token
->
Body
x + y
The body can be either a single expression or a block.
In the expression form, the body is simply evaluated and returned.
In the block form, the body is evaluated like a method body and a return statement returns control to the caller of the anonymous method. If the body produces a result, every control path must return something or throw an exception.
The parameter list can be empty: () -> …
Parameter types can be omitted. The compiler will in this case
infer types based on the “target type” of the place in the program
where the lambda expression occurs.
If there is only one parameter, the brace can be omitted.
Lambda-Expressions: Remarks
Java lambda-expressions always belong to a “functional interface” type with the precise type depending on the context
xs.sort((a,b) -> a – b); // Creates a comparator
IntBinaryOperator f = (a,b) -> a – b;
You cannot assign a lambda expression to an Object variable in either Java or C#:
Object obj = (a,b) -> a – b // does NOT compile
In the first example of xs, a and b types depend on what type the list xs is.
In the second example, since it’s an IntBinaryOperator, a and b would be integers
62
Delegates (C#) example revisited
public delegate bool MyPredicate(int value);
bool SelectPositive(int value)
{
return value > 0;
}
void PrintSelected(int[] list, MyPredicate select)
{
for (int i = 0; i < list.Length; i++)
if (select(list[i]))
Console.WriteLine(list[i]);
}
...
PrintSelected(list, SelectPositive);
Passing delegates (C#)
The SelectPositive method was defined as :
bool SelectPositive(int value)
{
return value > 0;
}
As with Java, this is a lot of code for a very simple concept
Lambda expressions allow much more compact syntax
You define the SelectPositive method (without giving it a name) at the point of calling PrintSelected
PrintSelected(list, x => x > 0);
Lambda expressions (C#)
Lambda expression is a block of code with parameters
Parameter List Arrow Token Body
(int x, int y) => x + y
The same principles as with Java lambda expressions
Capturing variables in lambda expressions (C#)
You are allowed to use outer variables inside the lambda expression:
int x = 5;
Func
Console.WriteLine(getValue());
Be careful; C# does not copy the values of the variables, hence the lambda expression will use the value as it is at the moment of invocation; for example, this code will output “10”:
int x = 5;
Func
x = 10;
Console.WriteLine(getValue());
END OF LECTURE
/docProps/thumbnail.jpeg