SlideShare ist ein Scribd-Unternehmen logo
1 von 107
#dotNETSpain2015
Leo Antoli @lantoli
Effective C#
.NET Conference 2015
Y
A
X B
#dotNETSpain2015
#dotNETSpain2015
WARNING:
Most of the code in
these slides is
about how NOT to
do it
#dotNETSpain2015
In order to master a language...
Wife mine this night
building an unusual
dinner at my home,
invited you are.
#dotNETSpain2015
Let's get started...
#dotNETSpain2015
string and String
Any difference ?
string a = "hello";
String b = "Hello";
#dotNETSpain2015
string and String
NO DIFFERENCE but prefer string
string -> C# alias for System.String
String -> System.String is a CLR type
#dotNETSpain2015
StringBuilder
string[] listStr = { "how ", "are", "you"};
string res = "";
foreach (string str in listStr) {
res += str;
}
#dotNETSpain2015
StringBuilder
string str = "a" + "b" + "c" + "d" + "e" + "f";
string str = new StringBuilder().
Append("a").Append("b").Append("c").
Append("d").Append("e").Append("f").ToString()
#dotNETSpain2015
Compiler makes some
initial work with constants
string str = "a" + "b" + "c" + "d" + "e" + "f";
Almost 10 times faster !!!
Slower:
string str = new StringBuilder().
Append("a").Append("b").Append("c").
Append("d").Append("e").Append("f").
ToString()
#dotNETSpain2015
Strong-typed Language
Any difference ?
int v = 10;
string res = "hello";
foreach (string str in listStr) { ... }
var v = 10;
var res = "hello";
foreach (var str in listStr) { ... }
#dotNETSpain2015
Overloading and Overriding
Parent p = new Parent(); Child c = new Child();
Parent c2 = new Child();
call(p);
call(c);
call(c2);
public class Child : Parent ...
public class Utilities {
void call(Parent o) { Console.WriteLine("Parent called"); }
void call(Child o) { Console.WriteLine("Child called"); }
#dotNETSpain2015
Overloading and Overriding
Polymorphism types:
Overloading (params) - compilation time - decide
method to call on input params
Overriding (inheritance) - execution - decide method to
call on instance class
Parent called
Child called
Parent called
#dotNETSpain2015
Overloading and Overriding
public Point(int x, int y) {...
public bool Equals(Point p) {
return x == p.x && y == p.y;
}
... GetHashCode ...
}
Point p1 = new Point(10,20);
Point p2 = new Point(10,20);
Console.WriteLine(p1.Equals(p2)); ???
HashSet<Point> set = new HashSet<Point>();
set.add(p1);
Console.WriteLine(set.Contains(p2)); ???
#dotNETSpain2015
Overloading and Overriding
true
false
public bool Equals(Point p)
public override bool Equals(object obj)
#dotNETSpain2015
String equality
string s1 = "hello";
string s2 = "HELLO".ToLower();
object o1 = s1;
object o2 = s2;
public void eq(bool expr) { Console.WriteLine(expr) };
eq( s1 == s2); // ???
eq( o1 == o2 ); // ???
eq( s1 == o2 ); // ???
eq( s1.Equals(s2) ); // ???
eq( s1.Equals(o2) ); // ???
eq( o1.Equals(s2) ); // ???
#dotNETSpain2015
String equality
string s1 = "hello";
string s2 = "HELLO".ToLower();
object o1 = s1;
object o2 = s2;
public void eq(bool expr) { Console.WriteLine(expr) };
eq( s1 == s2 ); // True
eq( o1 == o2 ); // False
eq( s1 == o2 ); // False
eq( s1.Equals(s2) ); // True
eq( s1.Equals(o2) ); // True
eq( o1.Equals(s2) ); // True
#dotNETSpain2015
String equality
Operators are static methods.
Static methods can be overloaded but not
overridden (can't be inherited).
So decision is in compilation time.
public static bool == (String left, String right)
#dotNETSpain2015
Inheritance override
interface Inter { void Message(); }
class A : Inter {
public void Message() { Console.WriteLine("A"); }}
class B : A {
public new void Message() { Console.WriteLine("B"); }}
B b = new B();
b.Message(); // ???
((Inter)b).Message(); // ???
((A)b).Message(); // ???
A a = b;
a.Message(); // ???
((Inter)a).Message(); // ???
#dotNETSpain2015
Inheritance override
VIRTUAL, OVERRIDE, SEALED, NEW
B b = new B();
b.Message(); // B
((Inter)b).Message(); // A
((A)b).Message(); // A
A a = b;
a.Message(); // A
((Inter)a).Message(); // A
TRY TO AVOID:
- Different behavior depending on the reference type
- Avoid "new" to redefine sealed methods
- Avoid explicit interface implementation
#dotNETSpain2015
Inheritance override
Design for inheritance or else prohibit it
public class Inheritable {
virtual public void Message() { ... }
...
sealed public class DontInherit {
public new void Message() { ... }
...
#dotNETSpain2015
Test data in a fast way
string[] strs = {"hello", "how", "are", "you"};
int[] ints = {10, 20, 30};
Point[] points = { new Point(10, 20), new Point(20, 40)};
List<string> list = new List<string>();
list.Add("hello");
list.Add("how");
Dictionary<string,int> dict = new Dictionary<string,int>();
dict.Add("hello", 13);
dict.Add("how", 15);
#dotNETSpain2015
Test data in a fast way
string[] strs = {"hello", "how", "are", "you"};
int[] ints = {10, 20, 30};
Point[] points = { new Point(10, 20), new Point(20, 40)};
If Enumerable and Add method:
var list = new List<string> {"hello", "how"};
var dict = new Dictionary<string,int> {
{ "hello", 13 },
{ "how", 15 },
};
#dotNETSpain2015
CLR & C#
+ +
+ +C
#dotNETSpain2015
CLR & C# (assembly compatibility)
#dotNETSpain2015
CLR & C# (properties vs fields)
FIELD:
public String Description;
PROPERTY:
private String comment;
public String Comment
{
get { return comment; }
set { comment = value; }
}
#dotNETSpain2015
CLR & C# (properties vs fields)
FIELD: Binary incompatible if later changed to property
public String Description;
public String Description { get; set; }
Implementation changes keep binary compatibility
Never user public fields
#dotNETSpain2015
CLR & C# (readonly vs const)
public const int DefaultPageSize = 10;
public static int DefaultPageSize2 { get { return 10; } }
public static readonly int DefaultPageSize3 = 10;
#dotNETSpain2015
CLR & C# (readonly vs const)
public const int DefaultPageSize = 10;
public static int DefaultPageSize2 { get { return 10; } }
public static readonly int DefaultPageSize3 = 10;
Const -> compilation-time (If assembly with const changes, all consumers
must recompile, const is not supported in CLR)
Only constant values, only simple types, ...
Readonly -> runtime
Never user public const if value could change in the future
#dotNETSpain2015
CLR & C# (readonly)
Can be set in constructor, can't be set after object is created
private readonly int _elementCount;
public int ElementCount { get { return _elementCount; } }
MyClass(int pages, int pageSize)
{
_elementCount = pages * pageSize;
}
THIS CAN BE CHANGED:
public int ElementCount2 { get; private set; }
#dotNETSpain2015
Any difference ?
public void Method1(String param1 = "hello", int param2 = 10)
{
// DO STUFF HERE
}
public void Method2() {Method2("hello");}
public void Method2(String param1) { Method2(param1, 10);}
public void Method2(String param1, int param2)
{
// DO STUFF HERE
}
CLR & C# (optional params)
#dotNETSpain2015
Default param values (and named params)
are in callsite assembly CIL.
If default values (or names) change in calling
site, all callsite assemblies must be
recompiled
public void Method1(String param1 = "BYE", int param2 = 10)
{
// DO STUFF HERE
}
CLR & C# (optional params)
#dotNETSpain2015
Pros and cons ?
Point p = new Point(x: 10, y: 20);
Point p = new Point { X=10, Y=20 };
CLR & C# (optional params
vs object initializers)
#dotNETSpain2015
Pros and cons ?
Point p = new Point(x: 10, y: 20);
EQUIVALENT TO:
Point p = new Point(10, 20);
Point p = new Point { X=10, Y=20 };
EQUIVALENT TO:
Point p = new Point();
p.X = 10;
p.Y = 20;
CLR & C# (optional params
vs object initializers)
#dotNETSpain2015
static class StringMethods {
public static bool IsLengthEven(this String str) {
return (str.Length & 1 ) == 1;
}
}
Console.WriteLine("is even hello: " + "hello".IsLengthEven());
Console.WriteLine("is even hello!: " + "hello!".IsLengthEven());
CLR & C# (extension methods)
#dotNETSpain2015
Value and Reference
Types
#dotNETSpain2015
Value and Reference types
C# is not a PURE OO language, not
everything is an object.
Heap / Stack
Reference: class, interface, delegate, array
Value: Predefined types (except string,
object), struct, enum
#dotNETSpain2015
Enum
public enum Quarter
{
Q1 = 1,
Q2 = 2,
Q3 = 3,
Q4 = 4
};
Quarter q1 = Quarter.Q1;
Quarter qa;
Quarter qb = new Quarter();
Console.WriteLine("q1: " + q1); // ???
Console.WriteLine("qa: " + qa); // ???
Console.WriteLine("qb: " + qb); // ???
#dotNETSpain2015
Enum
public enum Quarter
{
Q1 = 1, Q2 = 2, Q3 = 3, Q4 = 4
};
Quarter q1 = Quarter.Q1;
Quarter qa;
Quarter qb = new Quarter();
Console.WriteLine("q1: " + q1); // Q1
Console.WriteLine("qa: " + qa); // Compilation error because local var,
it would work in fields.
Console.WriteLine("qb: " + qb); // 0 Value types initialized to 0 or
default value
#dotNETSpain2015
Struct arrays
PointC[] c = new PointC[1000]; // Any diference ???
for (int i = 0; i < c.Length; i++)
{
c[i] = new PointC {X = i};
}
PointS[] s = new PointS[1000]; // Any diference ???
for (int i = 0; i < s.Length; i++)
{
s[i] = new PointS { X = i };
}
#dotNETSpain2015
Struct arrays
PointC[] c = new PointC[1000];
// HERE 1000 NULL REFERENCES ARE CREATED
for (int i = 0; i < c.Length; i++) {
c[i] = new PointC {X = i};
}
PointS[] s = new PointS[1000];
// HERE 1000 STRUTS WITH X,Y=0 ARE CREATED
for (int i = 0; i < s.Length; i++) {
s[i] = new PointS { X = i };
}
#dotNETSpain2015
Struct constructor
struct NegativePoint {
public NegativePoint(int x, int y) : this() { X = x; Y = y; }
private int x; private int y;
public int X {
set
{
if (value >= 0) throw
new ArgumentOutOfRangeException("X must be negative");
x = value;
}
get { return x; }
...
NegativePoint pa = new NegativePoint(0, 0); /// ???
NegativePoint pb = new NegativePoint(-5,-10); /// Can we enforce negative X,Y
?
#dotNETSpain2015
Struct constructor
Default public constructor always exists in structs
NegativePoint pa = new NegativePoint(); /// Create invalid point 0,0
NegativePoint pa = new NegativePoint(0, 0); /// throws exception
NegativePoint pb = new NegativePoint(-5,-10); /// OK
#dotNETSpain2015
Structs & Value Types
- Normally used for performance issues (be sure you get it)
- Non-nullable (uninitialized struct has default values)
- No references (e.g. copy when passed as parameters)
- So two references can not point to the same struct (pointA =
pointB makes a copy), except ref params
- Sealed (no inheritance allowed)
- Default public constructor always exists (can not enforce valid
state)
- Always implement Equals to avoid reflection
#dotNETSpain2015
Reference Parameters
(ref, out)
void Increment(int number) { number++; }
void IncrementRef(ref int number) { number++; }
int a = 10;
int b = 10;
Increment(a);
IncrementRef(ref b);
Console.WriteLine("A: " + a); /// ???
Console.WriteLine("B: " + b); /// ???
#dotNETSpain2015
Reference Parameters
(ref, out)
Ref is as an alias or reference, it's an in/out param
Console.WriteLine("A: " + a); /// 10
Console.WriteLine("B: " + b); /// 11
#dotNETSpain2015
Reference Parameters
(ref, out)
void Inc1(Point p) { p.X++; }
void Inc2(Point p) {
p = new Point { X = p.X + 1, Y = p.Y };
}
void IncRef(ref Point p) {
p = new Point { X = p.X + 1, Y = p.Y };
}
Point pa = new Point {X = 1, Y = 1}; Inc1(pa);
Point pb = new Point { X = 1, Y = 1 }; Inc2(pb);
Point pc = new Point { X = 1, Y = 1 }; IncRef(ref pc);
/// pa.X, pb.X, pc.X ???
#dotNETSpain2015
Reference Parameters
(ref, out)
void Inc1(Point p) { p.X++; }
void Inc2(Point p) {
p = new Point { X = p.X + 1, Y = p.Y };
}
void IncRef(ref Point p) {
p = new Point { X = p.X + 1, Y = p.Y };
}
/// pa.X = 2
/// pb.X = 1
/// pc.X = 2 (pc is referencing a new object)
#dotNETSpain2015
Generics
#dotNETSpain2015
Generic classes
public class MyList<T> {
public void Add(T elem)
{
...
}
...
}
MyList<int> listInts = new MyList<int>();
MyList<Car> listCars = new MyList<Car>();
MyList<Vehicle> listVehicles = new MyList<Vehicle>();
MyList<Vehicle> list = new MyList<Car> (); /// Are generics covariant
???
Vehicle[] arr = new Car[10]; /// Are arrays covariant ???
#dotNETSpain2015
Generic classes
Generics are invariant, arrays are covariant.
MyList<Vehicle> = new MyList<Car> (); /// Compile error
Vehicle[] arr = new Car[10]; /// OK, maybe runtime exceptions
string[] strarray = {"hello", "bye"};
object[] objarray = strarray;
objarray[0] = 123; /// ArrayTypeMismatchException
Vehicle[] vs = new Car[10];
vs[0] = new Motorbike(); /// ArrayTypeMismatchException
#dotNETSpain2015
Constraints on Generics
Assignments ?
T elm = null;
T elm = new T();
Common ancestor ?
T elm;
elm.X = 10;
#dotNETSpain2015
Constraints on Generics
class MyClass<T> where T:
ClassOrInterface, // base class or interface
class, // any reference type
struct, // any value type
new() // with default public constructor
T elm = default(T); // null or 0-based value
#dotNETSpain2015
Variance in generic delegates
public delegate T Factory<T>();
void FillGarage(int numVehicles, Factory<Vehicle> factory) { /* ... */ }
Factory<Car> carFactory = () => new Car();
Factory<Vehicle> vehicleFactory = carFactory; // compile error
FillGarage(10, carFactory); // compile error
public delegate bool Predicate<T>(T elm);
void SendCarsToRepair(Car c, Predicate<Car> pred) {
if (pred(c)) {
...
Predicate<Vehicle> predFord = elm => elm.Make == "Ford";
SendCarsToRepair(myCar, predFord); // compile error
#dotNETSpain2015
Covariance (out) and
contravariance (in)
public delegate T Factory<out T>();
void FillGarage(int numVehicles, Factory<Vehicle> factory) { /* ... */ }
Factory<Car> carFactory = () => new Car();
Factory<Vehicle> vehicleFactory = carFactory; // NO compile error
FillGarage(10, carFactory); // NO compile error
public delegate bool Predicate<in T>(T elm);
void SendCarsToRepair(Car c, Predicate<Car> pred) {
if (pred(c)) {
...
Predicate<Vehicle> predFord = elm => elm.Make == "Ford";
SendCarsToRepair(myCar, predFord); // NO compile error
#dotNETSpain2015
Variance in interfaces
List<Car> carList = new List<Car>();
List<Vehicle> vehList = carList; // compile error
IEnumerable<Vehicle> enumVehicles = carList; // OK !!!
class MakeComparer : IComparer<Vehicle> {
public int Compare(Vehicle x, Vehicle y) { /* ... */
IComparer<Car> makeComp = new MakeComparer(); // OK !!!
Car[] cars = new Car[10];
Array.Sort(cars, makeComp); // OK
#dotNETSpain2015
Variance in interfaces
Covariant:
IEnumerable<out T>
IEnumerator<out T>
IQueryable<out T>
IGrouping<out TKey, out TElement>
Contravariant:
IComparer<in T>
IEqualityComparer<in T>
IComparable<in T>
#dotNETSpain2015
Numbers
#dotNETSpain2015
Special numbers
int a = ???
a == -a
int b = ???
b == -b
double d = ???
d != d
#dotNETSpain2015
Special numbers
int a = 0
a == -a
int b = int.MinValue
b == -b
double d = double.NaN
d != d But d.Equals(d) !!!
#dotNETSpain2015
int a = 5, b = 0;
int c = a / b; ???
int d = a % b; ???
int a = Integer.MaxValue - 2;
int b = a + 3; ???
int a = 1000000000;
int b = a * 2000000000; ???
#dotNETSpain2015
In integer arithmetics,
exceptions thrown in division by 0
int a = 5, b = 0;
int c = a / b; // DivideByZeroException
int d = a % b; // DivideByZeroException
int a = int.MaxValue - 2;
int b = a + 3; // b = -2147483646
int a = 1000000000;
int b = a * 2000000000; // b = 1321730048
#dotNETSpain2015
long l = 1000000000000L;
int i = (int) l; ???
double d = Math.Sqrt(-1); ???
double a = 5 , b = 0; ???
double c = a % b; ???
double d = a / b; ???
#dotNETSpain2015
No exceptions in floating -
point arithmetics
long l = 1000000000000L;
int i = (int) l; // i = -727379968
double d = Math.Sqrt(-1); // d = NaN
double a = 5 , b = 0;
double c = a % b; // c = NaN
double d = a / b; // d = Infinity
#dotNETSpain2015
Castings double to int
double nan = double.NaN;
double inf = double.PositiveInfinity;
double bignum = 1e20;
int inan = (int) nan; ???
int iinf = (int) inf; ???
int ibignum = (int) bignum; ???
#dotNETSpain2015
Castings double to int
int inan // int.MinValue
int iinf // int.MinValue
int ibignum // int.MinValue
#dotNETSpain2015
Floating-point precision
double a = Double.MaxValue
double b = a + 1; ???
#dotNETSpain2015
No floating-point when
high precision is required
double a = Double.MaxValue;
double b = a + 1;
// a = b = 1.79769313486232E308
double.Epsilon -> min. number different to 0
#dotNETSpain2015
Always use checked
integer arithmetic
(checked not available for floating-point
arithmetic)
checked {
...
}
System.ArithmeticException
System.DivideByZeroException
System.NotFiniteNumberException
System.OverflowException
#dotNETSpain2015
High precision floating-point
decimal (28 significant bits)
NO BigDecimal
BigInteger
#dotNETSpain2015
Watch out number overflows
Extra, Extra - Read All About It: Nearly All Binary
Searches and Mergesorts are Broken
1: public static int BinarySearch(int[] a, int key) {
2: int low = 0;
3: int high = a.length - 1;
4:
5: while (low <= high) {
6: int mid = (low + high) / 2;
7: int midVal = a[mid];
8:
9: if (midVal < key)
10: low = mid + 1
11: else if (midVal > key)
12: high = mid - 1;
13: else
14: return mid; // key found
15: }
16: return -(low + 1); // key not found.
17: }
#dotNETSpain2015
Right solution
int mid = low + ((high - low) / 2);
unsigned mid = (low + high) >> 1;
#dotNETSpain2015
Mutability
#dotNETSpain2015
What's an immutable class ?
public class Point {
private readonly int x,y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public virtual int X { get { return x; } }
public virtual int Y { get { return y; } }
...
void setPoint(Point p) ...
#dotNETSpain2015
They must be sealed (or all setters)
public class MyPoint : Point {
private int x2,y2;
public override int X {
get { return x2; }
set { x2 = value; }
}
...
MyPoint p = new MyPoint(10,20);
miobj.setPoint(p);
p.X = 30; // VALUE CHANGED
#dotNETSpain2015
Watch out maps and sets
with mutable objects
var map = new Dictionary<Point,string>();
Point p = new Point(10,20);
map[p] = "my point";
Console.WriteLine(map[p]);
p.X = 11;
Console.WriteLine(map[p]);
#dotNETSpain2015
Watch out maps and sets
with mutable objects
var map = new Dictionary<Point,string>();
Point p = new Point(10,20);
map[p] = "my point";
Console.WriteLine(map[p]); // "my point"
p.X = 11;
Console.WriteLine(map[p]); // KeyNotFoundException
#dotNETSpain2015
Can we bypass invariants ?
class Point {
public X { get; set;}
public Y {get; set; }
...
class Line {
public Point StartPoint {
get { return startPoint; }
set {
if (value.X > 0 && value.Y > 0) {
startPoint = value;
}
...
#dotNETSpain2015
Never returns mutable objects
Always set a copy of mutable objects
Point p = new Point (1,1);
line.StartPoint = p;
p.X = -10;
Point p = line.StartPoint;
p.X = -10;
#dotNETSpain2015
public class Student {
public String Name { get; private set; }
public List<Course> Courses { get; private set; }
...
#dotNETSpain2015
Lists are mutable
And non-empty arrays are mutable too
List<Course> list = student.Courses;
list.Add(myNewCourse);
list.Clear();
#dotNETSpain2015
To create immutable lists
Enumerable.Empty<T>
list.AsReadOnly
ReadOnlyCollection
#dotNETSpain2015
Mutable and immutable classes
Prefer immutable classes.
For value objects try to build it at the
beginning and avoid set methods.
Make defensive copies where necessary
#dotNETSpain2015
Inheritance
#dotNETSpain2015
Inheritance
In general prefer composition over
inheritance.
Inheritance breaks encapsulation.
#dotNETSpain2015
Inheritance
public class InstrumentedHashSet<E> : HashSet<E> {
public int addCount;
public bool add(T item) {
addCount++;
return base.Add(item);
}
public static void Method(HashSet<string> a, string value) {
a.Add(value);
….
}
var set = new Instrumented<string>();
Method(set, "hello");
Method(set, "bye");
#dotNETSpain2015
Inheritance
Returns 0 !!!
public new bool add(T item)
Warning CS0108 'Instrumented<T>.Add(T)' hides inherited member
'HashSet<T>.Add(T)'. Use the new keyword if hiding was intended.
#dotNETSpain2015
Have to know intimately
the class you inherit from
public class InstrumentedHashSet<E> extends HashSet<E> {
private int addCount = 0;
@Override public boolean add(E e) {
addCount++;
return super.add(e);
}
@Override public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
...
InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
s.addAll(Arrays.asList("How", "are", "you"));
System.out.println(s.addCount()); ???
#dotNETSpain2015
Problem when using
overridable methods internally
Returns 6 !!!
We need to know what public/overridable
methods do internally.
#dotNETSpain2015
Better to delegate
public class InstrumentedHashSet<E> extends Set<E> {
private int addCount = 0;
private Set<E> set = new HashSet<E>();
@Override public boolean add(E e) {
addCount++;
return set.add(e);
}
@Override public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return set.addAll(c);
}
…….
#dotNETSpain2015
Constructors and inheritance
public class Child : Parent {
private int value;
public Child(int value) {
this.value = value;
}
}
// What's the difference ???
public Child(int value) : base() {
this.value = value;
}
#dotNETSpain2015
Constructors and inheritance
public class Parent {
private int x;
public Parent(int x) {
this.x = x;
...
public Child(string value) {
this.value = value; // Is super called ???
}
#dotNETSpain2015
Sub sub = new Sub("hello"); // WHAT'S PRINTED ?
public class Super {
public Super() { Init(); }
virtual public void Init() { }
}
public class Sub : Super {
private String msg;
Sub(string msg) { this.msg = msg; }
override public void Init() {
msg = msg.ToUpper();
Console.WriteLine("MESSAGE: " + msg);
}
}
#dotNETSpain2015
Problem when calling
overridable methods in constructor
Constructors don't have to call overridable
methods
// NullReferenceException
The method is called from parent constructor
when the child part is not initialized yet.
#dotNETSpain2015
Equals and inheritance
Resharper / Generate equality members
public class Point
{
public int X {get; set; }
public int Y {get; set; }
}
#dotNETSpain2015
Equals and inheritance
protected bool Equals(Point other)
{ return X == other.X && Y == other.Y; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Point) obj);
}
Exactly the same type as "this"
#dotNETSpain2015
Liskov substitution
principle is not held
If S is a subtype of T, then objects of type T in a computer program can be
replaced by objects of type S (that is, objects of type S can be replacements
for objects of type T), without changing any important property of the
program.
public class ColorPoint : Point {
public string Color {get; set; }
...
var p1 = new Point {X=10, Y=20 };
var p2 = new Point {X=10, Y=20};
var pcolor = new ColorPoint {X=10, Y=20, Color="blue"};
p1.Equals(p2) // TRUE
p1.Equals(pcolor); // FALSE
#dotNETSpain2015
Equals and inheritance
Point:
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
var other = obj as Point;
return other != null && Equals(other);
}
ColorPoint:
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
var other = obj as ColorPoint;
return other != null && Equals(other);
}
protected bool Equals(ColorPoint other) {
return base.Equals(other) &&
string.Equals(Color, other.Color);
}
Equal or subtype of "Point"
#dotNETSpain2015
Symmetry rule is not held
var p = new Point {X=10, Y=20 };
var pcolor = new ColorPoint {X=10, Y=20,
Color="blue"};
p1.Equals(pcolor) // TRUE
pcolor.Equals(p1); // FALSE
#dotNETSpain2015
So we can make a special
check for parent classes
ColorPoint:
public override bool Equals(object obj)
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (!(obj is Point)) return false;
if (!(obj is ColorPoint)) return obj.Equals(this);
var other = obj as ColorPoint;
return other != null && Equals(other);
}
#dotNETSpain2015
Transitivity rule is not held
var pcolor1 = new ColorPoint {X=10, Y=20,
Color="blue"};
var pcolor2 = new ColorPoint {X=10, Y=20,
Color="red"};
var p = new Point {X=10, Y=20 };
pcolor1.Equals(p) // TRUE
p.Equals(pcolor2) // TRUE
pcolor1.Equals(pcolor2); // FALSE
#dotNETSpain2015
Quiz 1
uint[] foo = new uint[10];
object bar = foo;
Console.WriteLine("{0} {1} {2} {3}",
foo is uint[], // True
foo is int[], // ???
bar is uint[], // True
bar is int[]); // ???
#dotNETSpain2015
Quiz 1
uint[] foo = new uint[10];
object bar = foo;
Console.WriteLine("{0} {1} {2} {3}",
foo is uint[], // True
foo is int[], // False
bar is uint[], // True
bar is int[]); // True
#dotNETSpain2015
Quiz 1
The CLI has the concept of "assignment compatibility"... The assignment from source value to
target variable has to be "representation preserving".
One of the rules of the CLI is "if X is assignment compatible with Y then X[] is assignment
compatible with Y[]".
That is not a rule of C#. C#'s array covariance rule is "if X is a reference type implicitly
convertible to reference type Y (via a reference or identity conversion) then X[] is implicitly
convertible to Y[]". That is a subtly different rule!
http://blogs.msdn.com/b/ericlippert/archive/2009/09/24/why-is-covariance-of-value-typed-
arrays-inconsistent.aspx
#dotNETSpain2015
Quiz 2
short sss = 123;
object ooo = sss; // Boxing
// OK, compile error or runtime error ???
int iii = (int)sss;
int jjj = (int)(short)ooo;
int kkk = (int)ooo;
#dotNETSpain2015
Quiz 2
Why? Because a boxed T can only be unboxed to T
short sss = 123;
object ooo = sss; // Boxing
int iii = (int)sss; // OK
int jjj = (int)(short)ooo; // OK
int kkk = (int)ooo; // Runtime error
http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx
#dotNETSpain2015
Leo Antoli @lantoli
Effective C#
¡¡¡Si te ha gustado no olvides
rellenar la encuesta!!!
Thanks
Y
A
X B

Weitere ähnliche Inhalte

Was ist angesagt?

Inheritance and polymorphism
Inheritance and polymorphismInheritance and polymorphism
Inheritance and polymorphismmohamed sikander
 
RxJS ‘Marble’ programming
RxJS ‘Marble’ programmingRxJS ‘Marble’ programming
RxJS ‘Marble’ programmingStas Rivkin
 
C Code and the Art of Obfuscation
C Code and the Art of ObfuscationC Code and the Art of Obfuscation
C Code and the Art of Obfuscationguest9006ab
 
Program for hamming code using c
Program for hamming code using cProgram for hamming code using c
Program for hamming code using csnsanth
 
Pads lab manual final
Pads lab manual finalPads lab manual final
Pads lab manual finalAhalyaR
 
C# 6.0 - April 2014 preview
C# 6.0 - April 2014 previewC# 6.0 - April 2014 preview
C# 6.0 - April 2014 previewPaulo Morgado
 
Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Aman Deep
 
C++ Programming - 11th Study
C++ Programming - 11th StudyC++ Programming - 11th Study
C++ Programming - 11th StudyChris Ohk
 
Cd practical file (1) start se
Cd practical file (1) start seCd practical file (1) start se
Cd practical file (1) start sedalipkumar64
 
Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)Damien Seguy
 
Computer Networks Lab File
Computer Networks Lab FileComputer Networks Lab File
Computer Networks Lab FileKandarp Tiwari
 

Was ist angesagt? (20)

Inheritance and polymorphism
Inheritance and polymorphismInheritance and polymorphism
Inheritance and polymorphism
 
C programs
C programsC programs
C programs
 
C++ file
C++ fileC++ file
C++ file
 
Implementing stack
Implementing stackImplementing stack
Implementing stack
 
Static and const members
Static and const membersStatic and const members
Static and const members
 
RxJS ‘Marble’ programming
RxJS ‘Marble’ programmingRxJS ‘Marble’ programming
RxJS ‘Marble’ programming
 
C Code and the Art of Obfuscation
C Code and the Art of ObfuscationC Code and the Art of Obfuscation
C Code and the Art of Obfuscation
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Bijender (1)
Bijender (1)Bijender (1)
Bijender (1)
 
Cquestions
Cquestions Cquestions
Cquestions
 
Program for hamming code using c
Program for hamming code using cProgram for hamming code using c
Program for hamming code using c
 
Implementing string
Implementing stringImplementing string
Implementing string
 
Pads lab manual final
Pads lab manual finalPads lab manual final
Pads lab manual final
 
Qno 1 (e)
Qno 1 (e)Qno 1 (e)
Qno 1 (e)
 
C# 6.0 - April 2014 preview
C# 6.0 - April 2014 previewC# 6.0 - April 2014 preview
C# 6.0 - April 2014 preview
 
Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output)
 
C++ Programming - 11th Study
C++ Programming - 11th StudyC++ Programming - 11th Study
C++ Programming - 11th Study
 
Cd practical file (1) start se
Cd practical file (1) start seCd practical file (1) start se
Cd practical file (1) start se
 
Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)Php in the graph (Gremlin 3)
Php in the graph (Gremlin 3)
 
Computer Networks Lab File
Computer Networks Lab FileComputer Networks Lab File
Computer Networks Lab File
 

Ähnlich wie Effective C#

Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 
Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Ismar Silveira
 
basic programs in C++
basic programs in C++ basic programs in C++
basic programs in C++ Arun Nair
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTsKevlin Henney
 
Program flowchart
Program flowchartProgram flowchart
Program flowchartSowri Rajan
 
Lab. Programs in C
Lab. Programs in CLab. Programs in C
Lab. Programs in CSaket Pathak
 
Arduino coding class
Arduino coding classArduino coding class
Arduino coding classJonah Marrs
 
2014 computer science_question_paper
2014 computer science_question_paper2014 computer science_question_paper
2014 computer science_question_papervandna123
 
Puzles C#
Puzles C#Puzles C#
Puzles C#lantoli
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperDeepak Singh
 
Rx.NET, from the inside out - Codemotion 2018
Rx.NET, from the inside out - Codemotion 2018Rx.NET, from the inside out - Codemotion 2018
Rx.NET, from the inside out - Codemotion 2018Stas Rivkin
 
Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018
Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018
Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018Codemotion
 
C++ Programming - 4th Study
C++ Programming - 4th StudyC++ Programming - 4th Study
C++ Programming - 4th StudyChris Ohk
 

Ähnlich wie Effective C# (20)

C program
C programC program
C program
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4
 
basic programs in C++
basic programs in C++ basic programs in C++
basic programs in C++
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTs
 
Program flowchart
Program flowchartProgram flowchart
Program flowchart
 
Lab. Programs in C
Lab. Programs in CLab. Programs in C
Lab. Programs in C
 
C programming
C programmingC programming
C programming
 
informatics practices practical file
informatics practices practical fileinformatics practices practical file
informatics practices practical file
 
Arduino coding class
Arduino coding classArduino coding class
Arduino coding class
 
Arrays
ArraysArrays
Arrays
 
DataTypes.ppt
DataTypes.pptDataTypes.ppt
DataTypes.ppt
 
2014 computer science_question_paper
2014 computer science_question_paper2014 computer science_question_paper
2014 computer science_question_paper
 
Puzles C#
Puzles C#Puzles C#
Puzles C#
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paper
 
Rx.NET, from the inside out - Codemotion 2018
Rx.NET, from the inside out - Codemotion 2018Rx.NET, from the inside out - Codemotion 2018
Rx.NET, from the inside out - Codemotion 2018
 
Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018
Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018
Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018
 
Novidades do c# 7 e 8
Novidades do c# 7 e 8Novidades do c# 7 e 8
Novidades do c# 7 e 8
 
C++ practical
C++ practicalC++ practical
C++ practical
 
C++ Programming - 4th Study
C++ Programming - 4th StudyC++ Programming - 4th Study
C++ Programming - 4th Study
 

Kürzlich hochgeladen

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 

Kürzlich hochgeladen (20)

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 

Effective C#

  • 1. #dotNETSpain2015 Leo Antoli @lantoli Effective C# .NET Conference 2015 Y A X B
  • 3. #dotNETSpain2015 WARNING: Most of the code in these slides is about how NOT to do it
  • 4. #dotNETSpain2015 In order to master a language... Wife mine this night building an unusual dinner at my home, invited you are.
  • 6. #dotNETSpain2015 string and String Any difference ? string a = "hello"; String b = "Hello";
  • 7. #dotNETSpain2015 string and String NO DIFFERENCE but prefer string string -> C# alias for System.String String -> System.String is a CLR type
  • 8. #dotNETSpain2015 StringBuilder string[] listStr = { "how ", "are", "you"}; string res = ""; foreach (string str in listStr) { res += str; }
  • 9. #dotNETSpain2015 StringBuilder string str = "a" + "b" + "c" + "d" + "e" + "f"; string str = new StringBuilder(). Append("a").Append("b").Append("c"). Append("d").Append("e").Append("f").ToString()
  • 10. #dotNETSpain2015 Compiler makes some initial work with constants string str = "a" + "b" + "c" + "d" + "e" + "f"; Almost 10 times faster !!! Slower: string str = new StringBuilder(). Append("a").Append("b").Append("c"). Append("d").Append("e").Append("f"). ToString()
  • 11. #dotNETSpain2015 Strong-typed Language Any difference ? int v = 10; string res = "hello"; foreach (string str in listStr) { ... } var v = 10; var res = "hello"; foreach (var str in listStr) { ... }
  • 12. #dotNETSpain2015 Overloading and Overriding Parent p = new Parent(); Child c = new Child(); Parent c2 = new Child(); call(p); call(c); call(c2); public class Child : Parent ... public class Utilities { void call(Parent o) { Console.WriteLine("Parent called"); } void call(Child o) { Console.WriteLine("Child called"); }
  • 13. #dotNETSpain2015 Overloading and Overriding Polymorphism types: Overloading (params) - compilation time - decide method to call on input params Overriding (inheritance) - execution - decide method to call on instance class Parent called Child called Parent called
  • 14. #dotNETSpain2015 Overloading and Overriding public Point(int x, int y) {... public bool Equals(Point p) { return x == p.x && y == p.y; } ... GetHashCode ... } Point p1 = new Point(10,20); Point p2 = new Point(10,20); Console.WriteLine(p1.Equals(p2)); ??? HashSet<Point> set = new HashSet<Point>(); set.add(p1); Console.WriteLine(set.Contains(p2)); ???
  • 15. #dotNETSpain2015 Overloading and Overriding true false public bool Equals(Point p) public override bool Equals(object obj)
  • 16. #dotNETSpain2015 String equality string s1 = "hello"; string s2 = "HELLO".ToLower(); object o1 = s1; object o2 = s2; public void eq(bool expr) { Console.WriteLine(expr) }; eq( s1 == s2); // ??? eq( o1 == o2 ); // ??? eq( s1 == o2 ); // ??? eq( s1.Equals(s2) ); // ??? eq( s1.Equals(o2) ); // ??? eq( o1.Equals(s2) ); // ???
  • 17. #dotNETSpain2015 String equality string s1 = "hello"; string s2 = "HELLO".ToLower(); object o1 = s1; object o2 = s2; public void eq(bool expr) { Console.WriteLine(expr) }; eq( s1 == s2 ); // True eq( o1 == o2 ); // False eq( s1 == o2 ); // False eq( s1.Equals(s2) ); // True eq( s1.Equals(o2) ); // True eq( o1.Equals(s2) ); // True
  • 18. #dotNETSpain2015 String equality Operators are static methods. Static methods can be overloaded but not overridden (can't be inherited). So decision is in compilation time. public static bool == (String left, String right)
  • 19. #dotNETSpain2015 Inheritance override interface Inter { void Message(); } class A : Inter { public void Message() { Console.WriteLine("A"); }} class B : A { public new void Message() { Console.WriteLine("B"); }} B b = new B(); b.Message(); // ??? ((Inter)b).Message(); // ??? ((A)b).Message(); // ??? A a = b; a.Message(); // ??? ((Inter)a).Message(); // ???
  • 20. #dotNETSpain2015 Inheritance override VIRTUAL, OVERRIDE, SEALED, NEW B b = new B(); b.Message(); // B ((Inter)b).Message(); // A ((A)b).Message(); // A A a = b; a.Message(); // A ((Inter)a).Message(); // A TRY TO AVOID: - Different behavior depending on the reference type - Avoid "new" to redefine sealed methods - Avoid explicit interface implementation
  • 21. #dotNETSpain2015 Inheritance override Design for inheritance or else prohibit it public class Inheritable { virtual public void Message() { ... } ... sealed public class DontInherit { public new void Message() { ... } ...
  • 22. #dotNETSpain2015 Test data in a fast way string[] strs = {"hello", "how", "are", "you"}; int[] ints = {10, 20, 30}; Point[] points = { new Point(10, 20), new Point(20, 40)}; List<string> list = new List<string>(); list.Add("hello"); list.Add("how"); Dictionary<string,int> dict = new Dictionary<string,int>(); dict.Add("hello", 13); dict.Add("how", 15);
  • 23. #dotNETSpain2015 Test data in a fast way string[] strs = {"hello", "how", "are", "you"}; int[] ints = {10, 20, 30}; Point[] points = { new Point(10, 20), new Point(20, 40)}; If Enumerable and Add method: var list = new List<string> {"hello", "how"}; var dict = new Dictionary<string,int> { { "hello", 13 }, { "how", 15 }, };
  • 25. #dotNETSpain2015 CLR & C# (assembly compatibility)
  • 26. #dotNETSpain2015 CLR & C# (properties vs fields) FIELD: public String Description; PROPERTY: private String comment; public String Comment { get { return comment; } set { comment = value; } }
  • 27. #dotNETSpain2015 CLR & C# (properties vs fields) FIELD: Binary incompatible if later changed to property public String Description; public String Description { get; set; } Implementation changes keep binary compatibility Never user public fields
  • 28. #dotNETSpain2015 CLR & C# (readonly vs const) public const int DefaultPageSize = 10; public static int DefaultPageSize2 { get { return 10; } } public static readonly int DefaultPageSize3 = 10;
  • 29. #dotNETSpain2015 CLR & C# (readonly vs const) public const int DefaultPageSize = 10; public static int DefaultPageSize2 { get { return 10; } } public static readonly int DefaultPageSize3 = 10; Const -> compilation-time (If assembly with const changes, all consumers must recompile, const is not supported in CLR) Only constant values, only simple types, ... Readonly -> runtime Never user public const if value could change in the future
  • 30. #dotNETSpain2015 CLR & C# (readonly) Can be set in constructor, can't be set after object is created private readonly int _elementCount; public int ElementCount { get { return _elementCount; } } MyClass(int pages, int pageSize) { _elementCount = pages * pageSize; } THIS CAN BE CHANGED: public int ElementCount2 { get; private set; }
  • 31. #dotNETSpain2015 Any difference ? public void Method1(String param1 = "hello", int param2 = 10) { // DO STUFF HERE } public void Method2() {Method2("hello");} public void Method2(String param1) { Method2(param1, 10);} public void Method2(String param1, int param2) { // DO STUFF HERE } CLR & C# (optional params)
  • 32. #dotNETSpain2015 Default param values (and named params) are in callsite assembly CIL. If default values (or names) change in calling site, all callsite assemblies must be recompiled public void Method1(String param1 = "BYE", int param2 = 10) { // DO STUFF HERE } CLR & C# (optional params)
  • 33. #dotNETSpain2015 Pros and cons ? Point p = new Point(x: 10, y: 20); Point p = new Point { X=10, Y=20 }; CLR & C# (optional params vs object initializers)
  • 34. #dotNETSpain2015 Pros and cons ? Point p = new Point(x: 10, y: 20); EQUIVALENT TO: Point p = new Point(10, 20); Point p = new Point { X=10, Y=20 }; EQUIVALENT TO: Point p = new Point(); p.X = 10; p.Y = 20; CLR & C# (optional params vs object initializers)
  • 35. #dotNETSpain2015 static class StringMethods { public static bool IsLengthEven(this String str) { return (str.Length & 1 ) == 1; } } Console.WriteLine("is even hello: " + "hello".IsLengthEven()); Console.WriteLine("is even hello!: " + "hello!".IsLengthEven()); CLR & C# (extension methods)
  • 37. #dotNETSpain2015 Value and Reference types C# is not a PURE OO language, not everything is an object. Heap / Stack Reference: class, interface, delegate, array Value: Predefined types (except string, object), struct, enum
  • 38. #dotNETSpain2015 Enum public enum Quarter { Q1 = 1, Q2 = 2, Q3 = 3, Q4 = 4 }; Quarter q1 = Quarter.Q1; Quarter qa; Quarter qb = new Quarter(); Console.WriteLine("q1: " + q1); // ??? Console.WriteLine("qa: " + qa); // ??? Console.WriteLine("qb: " + qb); // ???
  • 39. #dotNETSpain2015 Enum public enum Quarter { Q1 = 1, Q2 = 2, Q3 = 3, Q4 = 4 }; Quarter q1 = Quarter.Q1; Quarter qa; Quarter qb = new Quarter(); Console.WriteLine("q1: " + q1); // Q1 Console.WriteLine("qa: " + qa); // Compilation error because local var, it would work in fields. Console.WriteLine("qb: " + qb); // 0 Value types initialized to 0 or default value
  • 40. #dotNETSpain2015 Struct arrays PointC[] c = new PointC[1000]; // Any diference ??? for (int i = 0; i < c.Length; i++) { c[i] = new PointC {X = i}; } PointS[] s = new PointS[1000]; // Any diference ??? for (int i = 0; i < s.Length; i++) { s[i] = new PointS { X = i }; }
  • 41. #dotNETSpain2015 Struct arrays PointC[] c = new PointC[1000]; // HERE 1000 NULL REFERENCES ARE CREATED for (int i = 0; i < c.Length; i++) { c[i] = new PointC {X = i}; } PointS[] s = new PointS[1000]; // HERE 1000 STRUTS WITH X,Y=0 ARE CREATED for (int i = 0; i < s.Length; i++) { s[i] = new PointS { X = i }; }
  • 42. #dotNETSpain2015 Struct constructor struct NegativePoint { public NegativePoint(int x, int y) : this() { X = x; Y = y; } private int x; private int y; public int X { set { if (value >= 0) throw new ArgumentOutOfRangeException("X must be negative"); x = value; } get { return x; } ... NegativePoint pa = new NegativePoint(0, 0); /// ??? NegativePoint pb = new NegativePoint(-5,-10); /// Can we enforce negative X,Y ?
  • 43. #dotNETSpain2015 Struct constructor Default public constructor always exists in structs NegativePoint pa = new NegativePoint(); /// Create invalid point 0,0 NegativePoint pa = new NegativePoint(0, 0); /// throws exception NegativePoint pb = new NegativePoint(-5,-10); /// OK
  • 44. #dotNETSpain2015 Structs & Value Types - Normally used for performance issues (be sure you get it) - Non-nullable (uninitialized struct has default values) - No references (e.g. copy when passed as parameters) - So two references can not point to the same struct (pointA = pointB makes a copy), except ref params - Sealed (no inheritance allowed) - Default public constructor always exists (can not enforce valid state) - Always implement Equals to avoid reflection
  • 45. #dotNETSpain2015 Reference Parameters (ref, out) void Increment(int number) { number++; } void IncrementRef(ref int number) { number++; } int a = 10; int b = 10; Increment(a); IncrementRef(ref b); Console.WriteLine("A: " + a); /// ??? Console.WriteLine("B: " + b); /// ???
  • 46. #dotNETSpain2015 Reference Parameters (ref, out) Ref is as an alias or reference, it's an in/out param Console.WriteLine("A: " + a); /// 10 Console.WriteLine("B: " + b); /// 11
  • 47. #dotNETSpain2015 Reference Parameters (ref, out) void Inc1(Point p) { p.X++; } void Inc2(Point p) { p = new Point { X = p.X + 1, Y = p.Y }; } void IncRef(ref Point p) { p = new Point { X = p.X + 1, Y = p.Y }; } Point pa = new Point {X = 1, Y = 1}; Inc1(pa); Point pb = new Point { X = 1, Y = 1 }; Inc2(pb); Point pc = new Point { X = 1, Y = 1 }; IncRef(ref pc); /// pa.X, pb.X, pc.X ???
  • 48. #dotNETSpain2015 Reference Parameters (ref, out) void Inc1(Point p) { p.X++; } void Inc2(Point p) { p = new Point { X = p.X + 1, Y = p.Y }; } void IncRef(ref Point p) { p = new Point { X = p.X + 1, Y = p.Y }; } /// pa.X = 2 /// pb.X = 1 /// pc.X = 2 (pc is referencing a new object)
  • 50. #dotNETSpain2015 Generic classes public class MyList<T> { public void Add(T elem) { ... } ... } MyList<int> listInts = new MyList<int>(); MyList<Car> listCars = new MyList<Car>(); MyList<Vehicle> listVehicles = new MyList<Vehicle>(); MyList<Vehicle> list = new MyList<Car> (); /// Are generics covariant ??? Vehicle[] arr = new Car[10]; /// Are arrays covariant ???
  • 51. #dotNETSpain2015 Generic classes Generics are invariant, arrays are covariant. MyList<Vehicle> = new MyList<Car> (); /// Compile error Vehicle[] arr = new Car[10]; /// OK, maybe runtime exceptions string[] strarray = {"hello", "bye"}; object[] objarray = strarray; objarray[0] = 123; /// ArrayTypeMismatchException Vehicle[] vs = new Car[10]; vs[0] = new Motorbike(); /// ArrayTypeMismatchException
  • 52. #dotNETSpain2015 Constraints on Generics Assignments ? T elm = null; T elm = new T(); Common ancestor ? T elm; elm.X = 10;
  • 53. #dotNETSpain2015 Constraints on Generics class MyClass<T> where T: ClassOrInterface, // base class or interface class, // any reference type struct, // any value type new() // with default public constructor T elm = default(T); // null or 0-based value
  • 54. #dotNETSpain2015 Variance in generic delegates public delegate T Factory<T>(); void FillGarage(int numVehicles, Factory<Vehicle> factory) { /* ... */ } Factory<Car> carFactory = () => new Car(); Factory<Vehicle> vehicleFactory = carFactory; // compile error FillGarage(10, carFactory); // compile error public delegate bool Predicate<T>(T elm); void SendCarsToRepair(Car c, Predicate<Car> pred) { if (pred(c)) { ... Predicate<Vehicle> predFord = elm => elm.Make == "Ford"; SendCarsToRepair(myCar, predFord); // compile error
  • 55. #dotNETSpain2015 Covariance (out) and contravariance (in) public delegate T Factory<out T>(); void FillGarage(int numVehicles, Factory<Vehicle> factory) { /* ... */ } Factory<Car> carFactory = () => new Car(); Factory<Vehicle> vehicleFactory = carFactory; // NO compile error FillGarage(10, carFactory); // NO compile error public delegate bool Predicate<in T>(T elm); void SendCarsToRepair(Car c, Predicate<Car> pred) { if (pred(c)) { ... Predicate<Vehicle> predFord = elm => elm.Make == "Ford"; SendCarsToRepair(myCar, predFord); // NO compile error
  • 56. #dotNETSpain2015 Variance in interfaces List<Car> carList = new List<Car>(); List<Vehicle> vehList = carList; // compile error IEnumerable<Vehicle> enumVehicles = carList; // OK !!! class MakeComparer : IComparer<Vehicle> { public int Compare(Vehicle x, Vehicle y) { /* ... */ IComparer<Car> makeComp = new MakeComparer(); // OK !!! Car[] cars = new Car[10]; Array.Sort(cars, makeComp); // OK
  • 57. #dotNETSpain2015 Variance in interfaces Covariant: IEnumerable<out T> IEnumerator<out T> IQueryable<out T> IGrouping<out TKey, out TElement> Contravariant: IComparer<in T> IEqualityComparer<in T> IComparable<in T>
  • 59. #dotNETSpain2015 Special numbers int a = ??? a == -a int b = ??? b == -b double d = ??? d != d
  • 60. #dotNETSpain2015 Special numbers int a = 0 a == -a int b = int.MinValue b == -b double d = double.NaN d != d But d.Equals(d) !!!
  • 61. #dotNETSpain2015 int a = 5, b = 0; int c = a / b; ??? int d = a % b; ??? int a = Integer.MaxValue - 2; int b = a + 3; ??? int a = 1000000000; int b = a * 2000000000; ???
  • 62. #dotNETSpain2015 In integer arithmetics, exceptions thrown in division by 0 int a = 5, b = 0; int c = a / b; // DivideByZeroException int d = a % b; // DivideByZeroException int a = int.MaxValue - 2; int b = a + 3; // b = -2147483646 int a = 1000000000; int b = a * 2000000000; // b = 1321730048
  • 63. #dotNETSpain2015 long l = 1000000000000L; int i = (int) l; ??? double d = Math.Sqrt(-1); ??? double a = 5 , b = 0; ??? double c = a % b; ??? double d = a / b; ???
  • 64. #dotNETSpain2015 No exceptions in floating - point arithmetics long l = 1000000000000L; int i = (int) l; // i = -727379968 double d = Math.Sqrt(-1); // d = NaN double a = 5 , b = 0; double c = a % b; // c = NaN double d = a / b; // d = Infinity
  • 65. #dotNETSpain2015 Castings double to int double nan = double.NaN; double inf = double.PositiveInfinity; double bignum = 1e20; int inan = (int) nan; ??? int iinf = (int) inf; ??? int ibignum = (int) bignum; ???
  • 66. #dotNETSpain2015 Castings double to int int inan // int.MinValue int iinf // int.MinValue int ibignum // int.MinValue
  • 67. #dotNETSpain2015 Floating-point precision double a = Double.MaxValue double b = a + 1; ???
  • 68. #dotNETSpain2015 No floating-point when high precision is required double a = Double.MaxValue; double b = a + 1; // a = b = 1.79769313486232E308 double.Epsilon -> min. number different to 0
  • 69. #dotNETSpain2015 Always use checked integer arithmetic (checked not available for floating-point arithmetic) checked { ... } System.ArithmeticException System.DivideByZeroException System.NotFiniteNumberException System.OverflowException
  • 70. #dotNETSpain2015 High precision floating-point decimal (28 significant bits) NO BigDecimal BigInteger
  • 71. #dotNETSpain2015 Watch out number overflows Extra, Extra - Read All About It: Nearly All Binary Searches and Mergesorts are Broken 1: public static int BinarySearch(int[] a, int key) { 2: int low = 0; 3: int high = a.length - 1; 4: 5: while (low <= high) { 6: int mid = (low + high) / 2; 7: int midVal = a[mid]; 8: 9: if (midVal < key) 10: low = mid + 1 11: else if (midVal > key) 12: high = mid - 1; 13: else 14: return mid; // key found 15: } 16: return -(low + 1); // key not found. 17: }
  • 72. #dotNETSpain2015 Right solution int mid = low + ((high - low) / 2); unsigned mid = (low + high) >> 1;
  • 74. #dotNETSpain2015 What's an immutable class ? public class Point { private readonly int x,y; public Point(int x, int y) { this.x = x; this.y = y; } public virtual int X { get { return x; } } public virtual int Y { get { return y; } } ... void setPoint(Point p) ...
  • 75. #dotNETSpain2015 They must be sealed (or all setters) public class MyPoint : Point { private int x2,y2; public override int X { get { return x2; } set { x2 = value; } } ... MyPoint p = new MyPoint(10,20); miobj.setPoint(p); p.X = 30; // VALUE CHANGED
  • 76. #dotNETSpain2015 Watch out maps and sets with mutable objects var map = new Dictionary<Point,string>(); Point p = new Point(10,20); map[p] = "my point"; Console.WriteLine(map[p]); p.X = 11; Console.WriteLine(map[p]);
  • 77. #dotNETSpain2015 Watch out maps and sets with mutable objects var map = new Dictionary<Point,string>(); Point p = new Point(10,20); map[p] = "my point"; Console.WriteLine(map[p]); // "my point" p.X = 11; Console.WriteLine(map[p]); // KeyNotFoundException
  • 78. #dotNETSpain2015 Can we bypass invariants ? class Point { public X { get; set;} public Y {get; set; } ... class Line { public Point StartPoint { get { return startPoint; } set { if (value.X > 0 && value.Y > 0) { startPoint = value; } ...
  • 79. #dotNETSpain2015 Never returns mutable objects Always set a copy of mutable objects Point p = new Point (1,1); line.StartPoint = p; p.X = -10; Point p = line.StartPoint; p.X = -10;
  • 80. #dotNETSpain2015 public class Student { public String Name { get; private set; } public List<Course> Courses { get; private set; } ...
  • 81. #dotNETSpain2015 Lists are mutable And non-empty arrays are mutable too List<Course> list = student.Courses; list.Add(myNewCourse); list.Clear();
  • 82. #dotNETSpain2015 To create immutable lists Enumerable.Empty<T> list.AsReadOnly ReadOnlyCollection
  • 83. #dotNETSpain2015 Mutable and immutable classes Prefer immutable classes. For value objects try to build it at the beginning and avoid set methods. Make defensive copies where necessary
  • 85. #dotNETSpain2015 Inheritance In general prefer composition over inheritance. Inheritance breaks encapsulation.
  • 86. #dotNETSpain2015 Inheritance public class InstrumentedHashSet<E> : HashSet<E> { public int addCount; public bool add(T item) { addCount++; return base.Add(item); } public static void Method(HashSet<string> a, string value) { a.Add(value); …. } var set = new Instrumented<string>(); Method(set, "hello"); Method(set, "bye");
  • 87. #dotNETSpain2015 Inheritance Returns 0 !!! public new bool add(T item) Warning CS0108 'Instrumented<T>.Add(T)' hides inherited member 'HashSet<T>.Add(T)'. Use the new keyword if hiding was intended.
  • 88. #dotNETSpain2015 Have to know intimately the class you inherit from public class InstrumentedHashSet<E> extends HashSet<E> { private int addCount = 0; @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } ... InstrumentedHashSet<String> s = new InstrumentedHashSet<>(); s.addAll(Arrays.asList("How", "are", "you")); System.out.println(s.addCount()); ???
  • 89. #dotNETSpain2015 Problem when using overridable methods internally Returns 6 !!! We need to know what public/overridable methods do internally.
  • 90. #dotNETSpain2015 Better to delegate public class InstrumentedHashSet<E> extends Set<E> { private int addCount = 0; private Set<E> set = new HashSet<E>(); @Override public boolean add(E e) { addCount++; return set.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return set.addAll(c); } …….
  • 91. #dotNETSpain2015 Constructors and inheritance public class Child : Parent { private int value; public Child(int value) { this.value = value; } } // What's the difference ??? public Child(int value) : base() { this.value = value; }
  • 92. #dotNETSpain2015 Constructors and inheritance public class Parent { private int x; public Parent(int x) { this.x = x; ... public Child(string value) { this.value = value; // Is super called ??? }
  • 93. #dotNETSpain2015 Sub sub = new Sub("hello"); // WHAT'S PRINTED ? public class Super { public Super() { Init(); } virtual public void Init() { } } public class Sub : Super { private String msg; Sub(string msg) { this.msg = msg; } override public void Init() { msg = msg.ToUpper(); Console.WriteLine("MESSAGE: " + msg); } }
  • 94. #dotNETSpain2015 Problem when calling overridable methods in constructor Constructors don't have to call overridable methods // NullReferenceException The method is called from parent constructor when the child part is not initialized yet.
  • 95. #dotNETSpain2015 Equals and inheritance Resharper / Generate equality members public class Point { public int X {get; set; } public int Y {get; set; } }
  • 96. #dotNETSpain2015 Equals and inheritance protected bool Equals(Point other) { return X == other.X && Y == other.Y; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; return Equals((Point) obj); } Exactly the same type as "this"
  • 97. #dotNETSpain2015 Liskov substitution principle is not held If S is a subtype of T, then objects of type T in a computer program can be replaced by objects of type S (that is, objects of type S can be replacements for objects of type T), without changing any important property of the program. public class ColorPoint : Point { public string Color {get; set; } ... var p1 = new Point {X=10, Y=20 }; var p2 = new Point {X=10, Y=20}; var pcolor = new ColorPoint {X=10, Y=20, Color="blue"}; p1.Equals(p2) // TRUE p1.Equals(pcolor); // FALSE
  • 98. #dotNETSpain2015 Equals and inheritance Point: public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; var other = obj as Point; return other != null && Equals(other); } ColorPoint: public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; var other = obj as ColorPoint; return other != null && Equals(other); } protected bool Equals(ColorPoint other) { return base.Equals(other) && string.Equals(Color, other.Color); } Equal or subtype of "Point"
  • 99. #dotNETSpain2015 Symmetry rule is not held var p = new Point {X=10, Y=20 }; var pcolor = new ColorPoint {X=10, Y=20, Color="blue"}; p1.Equals(pcolor) // TRUE pcolor.Equals(p1); // FALSE
  • 100. #dotNETSpain2015 So we can make a special check for parent classes ColorPoint: public override bool Equals(object obj) if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (!(obj is Point)) return false; if (!(obj is ColorPoint)) return obj.Equals(this); var other = obj as ColorPoint; return other != null && Equals(other); }
  • 101. #dotNETSpain2015 Transitivity rule is not held var pcolor1 = new ColorPoint {X=10, Y=20, Color="blue"}; var pcolor2 = new ColorPoint {X=10, Y=20, Color="red"}; var p = new Point {X=10, Y=20 }; pcolor1.Equals(p) // TRUE p.Equals(pcolor2) // TRUE pcolor1.Equals(pcolor2); // FALSE
  • 102. #dotNETSpain2015 Quiz 1 uint[] foo = new uint[10]; object bar = foo; Console.WriteLine("{0} {1} {2} {3}", foo is uint[], // True foo is int[], // ??? bar is uint[], // True bar is int[]); // ???
  • 103. #dotNETSpain2015 Quiz 1 uint[] foo = new uint[10]; object bar = foo; Console.WriteLine("{0} {1} {2} {3}", foo is uint[], // True foo is int[], // False bar is uint[], // True bar is int[]); // True
  • 104. #dotNETSpain2015 Quiz 1 The CLI has the concept of "assignment compatibility"... The assignment from source value to target variable has to be "representation preserving". One of the rules of the CLI is "if X is assignment compatible with Y then X[] is assignment compatible with Y[]". That is not a rule of C#. C#'s array covariance rule is "if X is a reference type implicitly convertible to reference type Y (via a reference or identity conversion) then X[] is implicitly convertible to Y[]". That is a subtly different rule! http://blogs.msdn.com/b/ericlippert/archive/2009/09/24/why-is-covariance-of-value-typed- arrays-inconsistent.aspx
  • 105. #dotNETSpain2015 Quiz 2 short sss = 123; object ooo = sss; // Boxing // OK, compile error or runtime error ??? int iii = (int)sss; int jjj = (int)(short)ooo; int kkk = (int)ooo;
  • 106. #dotNETSpain2015 Quiz 2 Why? Because a boxed T can only be unboxed to T short sss = 123; object ooo = sss; // Boxing int iii = (int)sss; // OK int jjj = (int)(short)ooo; // OK int kkk = (int)ooo; // Runtime error http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx
  • 107. #dotNETSpain2015 Leo Antoli @lantoli Effective C# ¡¡¡Si te ha gustado no olvides rellenar la encuesta!!! Thanks Y A X B