extends
, implements
:
super
base
final
readonly
, sealed
import
using
package
namespace {...}
instanceof
is
synchronized
lock x
finalize()
~ClassName()
(clean-up called by garbage collector)List<T>
uses a !0[]
array, avoiding type erasure and casting, unlike Java's ArrayList<T>
which uses Object[]
.using
statement.foreach
loop.params
keyword.using
extension methods.csharp
using (FileStream fs = File.OpenRead(path))
using (StreamReader sr = new StreamReader(fs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
csharp
enum TrafficLightColour {Red, RedAmber, Green, Amber};
TrafficLightColour tlc = TrafficLightColour.Red;
csharp
string[] presidents = new string[] { “Washington”, “Jefferson”, “Lincoln”, “Roosevelt” };
foreach (string president in presidents)
{
Console.WriteLine(president);
}
csharp
public static void SumList(params int[] list)
csharp
int[] somevalues = { 10, 20, 5, 2, 40, 1 };
int numberOfLargeValues = somevalues.Count(x => x >10);
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.throws
list on method declarations).checked
keyword to throw a System.OverflowException
if an overflow occurs.csharp
int x = 1000000;
int y = checked(x*x);
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;
}
byte
, ushort
, uint
, ulong
(for systems programming).decimal
type: For large decimal numbers with high accuracy (financial mathematics).System.Object
.List<int>
and insert int
without boxing.&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).*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).Lightweight objects for holding temporary data.
Held on the stack (no garbage collection).
Value types: copying has value semantics.
p
to q
and change q
, then p
won’t change.Objects are reference types: copying has reference semantics.
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
csharp
int[,] a = new int[2,3];
int[,] b = {{1, 2, 3}, {4, 5, 6}};
int[,,] c = new int[2,4,2];
csharp
dynamic s = GetObject();
Console.WriteLine(s.ToUpper()); // object s doesn’t work
var
, where the type is inferred statically.csharp
var numbers = new List<int>();
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);
csharp
class Person {
public string Name { get; set; }
}
Item
.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
}
}
In Java, all parameter passing is by value.
In C#, using the ref
keyword, passing can be by reference.
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
}
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() { }
}
yield return
for Lazy EvaluationExample:
public class PowersOf2 {
static void Main() {
foreach (int i in Power(2, 8)) {
Console.Write("{0} ", i);
}
}public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent) {
int result = 1;
for (int i = 0; i < exponent; i++) {
result = result * number;
yield return result;
}
// returns number^0 ... number^(exponent-1)
}
}
csharp
var results = from c in SomeCollection
where c.SomeProperty < 10
select new {c.SomeProperty, c.OtherProperty};
csharp
var results = SomeCollection
.Where(c => c.SomeProperty < 10)
.Select(c => new {c.SomeProperty, c.OtherProperty});
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
}
}