This presentation comes with many additional notes (pdf): http://de.slideshare.net/nicolayludwig/7-c-sharp-introductionadvanvcedfeaturespartii-38640489
Check out these exercises: http://de.slideshare.net/nicolayludwig/6-7-c-sharp-introductionadvancedfeaturespartipartiiexercises
- Object-based and generic Collections
- Delegates and Events
- Custom Attributes
- Reflection
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
(7) c sharp introduction_advanvced_features_part_ii
1. 1
(7) Introduction of C# Basics – Advanced Features
– Part II
Nico Ludwig (@ersatzteilchen)
2. 2
TOC
● (7) Introduction of C# – Advanced Features – Part II
– Object-based and generic Collections
– Delegates and Events
– Custom Attributes
– Reflection
3. 3
Collections
● Collections are types that represent a set of other objects (elements or items).
– Certain Collections differ in the way they manage access to their items.
– Roughly we tell sequential from associative Collections.
– Examples from namespace System.Collections: ArrayList, Hashtable, Queue or Stack.
● .Net collections manage references to objects, not the objects itself.
– Value type objects are being boxed into objects, when they are added.
● object-based Collections are not typesafe!
– One can easily introduce run time errors.
4. 4
Type Problems in Collections
// A collection of Objects (the static type of those is System.Object).
ArrayList aList = new ArrayList();
// One can add any type of Object into this collection.
aList.Add(new Bus());
// If we want to access the contained object's interface, we have probably
// to cast down to the dynamic type's interface.
object anObject = aList[0];
VintageCar aVintageCar = (VintageCar)anObject;
//... but we can fail here, e.g. if the actual dynamic type differs from the
// assumed dynamic type. -> Bus is a System.Object, but not a VintageCar!
// This cast will end in an InvalidCastException!
// We'll never reach this line:
double estimatedPrize = aVintageCar.EstimatedPrize;
5. 5
Generic Collections to the Rescue
● Generic collections allow to specify the type of the managed items.
– They live in the namespace System.Collections.Generic.
– A type name is used as argument for a generic type.
– The type names are specified in angle brackets: List<int> -> a list of int.
● Arrays act also like generic collections, but employ another syntax.
● Benefits compared to object-typed Collections:
– With generic types the compiler can check typesafety.
– Downcasting is not required.
● It is also possible to create own generic types:
– Generic classes, interfaces etc.
– The range of allowed generic types can be controlled with constraints.
6. 6
Generic Collections in Action
// A collection of VintageCars (static type).
List<VintageCar> aList = new List<VintageCar>(42);
// We can add any type of VintageCar into this collection.
aList.Add(new VintageCar());
// We can not add Cars, this is a too common type.
aList.Add(new Car()); // Compile time error
// We can not add Buses, this type is no kind of VintageCar.
aList.Add(new Bus()); // Compile time error
// If we want to access the contained object's interface,
// downcasting is not required, the assignment can not fail.
VintageCar aVintageCar = aList[0];
double estimatedPrize = aVintageCar.EstimatedPrize;
7. 7
Delegates
● Often there exist root-algorithms that call other sub-algorithms.
– The root-algorithm is always identical.
– Only the sub-algorithms are a matter of change.
– Example: The root-algorithm "Sort" has a fix structure, but it calls compare-algorithms to compare objects. For each object type
the compare-algorithm is probably different.
● The idea of root- and sub-algorithms make up some kind of "template".
– Root-algorithms such as "Sort" have a fix structure, the sub-algorithms vary.
– For sub-algorithms, interfaces must be defined that fit into that "template".
● .Net introduces the delegate concept to describe the interface of sub-algorithms in a type save manner.
– In C/C++ we have a similar the concept with function pointers.
8. 8
Example of Almost identical Algorithms
public void SortInts(List<int> elements) {
for (int x = 0; x < elements.Count - 1; ++x) {
for (int y = 0; y < elements.Count - 1 - x; ++y) {
if (elements[y] > elements[y + 1])
{
Swap(y, y + 1, elements);
}
}
}
}
public void SortStrings(List<string> elements) {
for (int x = 0; x < elements.Count - 1; ++x) {
for (int y = 0; y < elements.Count - 1 - x; ++y) {
if (0 < string.Compare(elements[y], elements[y + 1]))
{
Swap(y, y + 1, elements);
}
}
}
}
9. 9
Steps to improve the SortXXX Methods
● The comparison expression is the only difference in the implementations!
● Extract this sub-algorithm as method and define its signature as delegate:
public delegate int Compare<T>(T left, T right);
● Sort() gets passed a parameter of delegate type that represents a Compare() method implementation.
● Within Sort() the passed delegate is invoked and its returned value is analyzed.
– I.e. we'll pass another method as argument to the method Sort().
● In effect, the method Sort() is much more useful: it can sort any kinds of objects!
– The programmer has to define a suitable Compare() method.
– The Compare() method's identifier must be passed as argument.
10. 10
The same Algorithm with Delegates
// Definition of the signature of delegate methods:
public delegate int Compare<T>(T left, T right);
// Definition of the "template" algorithm:
public void Sort<T>(List<T> elements, Compare<T> cmp)
{
for (int x = 0; x < elements.Count - 1; ++x)
{
for (int y = 0; y < elements.Count - 1 - x; ++y)
{
// Here the delegate is called:
if (0 < cmp(elements[y], elements[y + 1]))
{
Swap(y, y + 1, elements);
}
}
}
}
11. 11
Delegates in Action
public static void Main(string[] args) {
List<string> sList = new List<string>(2);
sList.Add("World");
sList.Add("Hello");
List<int> iList = new List<int>(2);
iList.Add(2);
iList.Add(17);
// Here the method identifiers are passed as arguments, the Compare-
// operation is delegated to these methods.
Sort<string>(sList, CompareStrings);
Sort<int>(iList, CompareInts);
}
// Two methods with the signature of the delegate Compare:
public int CompareStrings(string s1, string s2) {
return string.Compare(s1, s2);
}
public int CompareInts(int i1, int i2) {
return i1.CompareTo(i2);
}
12. 12
Events
● Sometimes it is useful to get notified, when an object's state is updated.
– E.g. in Cars a notification when the Tank is almost empty is useful.
● Such notifications are implemented as events in the .Net framework.
– Syntactically events are special fields within a type that can refer to functions.
● Observers register to events:
– Registering to an event means to register a delegate instance to an event.
– E.g. the Driver object can register to Car's event TankEmpty to get notified.
– More than one observer can register to the event TankEmpty (multicasting).
● Observed objects can raise events:
– The event's type is a delegate that will be invoked from within the object.
– On raising the event, arguments can be passed as well.
13. 13
Class Car with the Event TankEmpty
// Define the delegate type for the event handler:
public delegate void TankEmptyEventHandler(string info);
public class Car {
// Define the event TankEmpty like a field in Car:
public event TankEmptyEventHandler TankEmpty;
public void EngineRunning() {
if (_tankRunningEmpty && null != TankEmpty) {
// Raise the event:
TankEmpty("Tank less than 5L!");
}
}
}
14. 14
Events in Action
// Two methods that may act as handler for TankEmpty event instances of
// TankEmptyEventHandler.
public static void ReportToConsole(string info) {
public static void Main(string[] args) {
Car car = new Car(); // Object car is being observed here.
// Register the two handlers (use operator -= to unregister). When the
// event is raised these two handlers (the observers) are being called.
car.TankEmpty += ReportToConsole;
car.TankEmpty += DashBoardSignal;
while (true) {
car.EngineRunning();
}
}
Console.WriteLine(info);
}
public static void DashBoardSignal(string info) {
TankEmptySignal.Set(true);
}
15. 15
Custom Attributes
● In C# .Net types and members can be annotated with C# attributes.
– E.g.: private, sealed or readonly.
● Custom attributes allow to add more metadata for a .Net element into IL.
– Declarative nature: A type's behavior is modified without modifying the type itself.
– Consumption: During run time this metadata can be read and interpreted via reflection.
● There exist many predefined run time and compile time custom attributes.
– Examples: FlagsAttribute, ConditionalAttribute, TestAttribute
– How to annotate: Custom attributes can be placed via direct or targeted syntax.
● Programmers can also define custom attributes.
– Custom attributes have to derive from System.Attribute.
16. 16
Compile Time Attribute “Conditional” in Action
public class Debug
{
// The method WriteLine is annotated with ConditionalAttribute("DEBUG"):
[System.Diagnostics.Conditional("DEBUG")]
public static void WriteLine(string message) { /*pass */ }
}
private void F()
{
// Due to the compile time ConditionalAttribute("DEBUG"), this method
// call is only compiled in the "DEBUG" configuration:
System.Diagnostics.Debug.WriteLine("Hello out there!");
}
17. 17
Reflection
● The .Net framework allows to analyze types during run time via reflection.
● Reflection is needed:
– If code must handle unknown types (members, hierarchies etc.).
● This was addressed with dynamic typing in .Net 4 as well.
– If code has to decide upon type features.
● E.g., if code has to analyze custom attributes.
● Reflection is accessible via the type Type and the namespace System.Reflection.
● Reflection should be used sparingly, because it is rather expensive.
– Better use polymorphism and design patterns.
18. 18
Reflecting Type "String"
public void Main() {
// Getting the type of String to start reflection:
Type theStringType = typeof(string);
// Reflecting all custom attributes (also the inherited ones) of the type string:
object[] customAttributes = theStringType.GetCustomAttributes(true);
for (int i = 0; i < customAttributes.Length; ++i) {
Attribute attribute = (Attribute)customAttributes[i];
Console.WriteLine(attribute);
}
// Reflecting all methods of the type String:
object[] methods = theStringType.GetMethods();
for (int i = 0; i < methods.Length; ++i) {
System.Reflection.MethodInfo methodInfo = (System.Reflection.MethodInfo)methods[i];
Console.WriteLine(methodInfo);
}
}
19. 19
C# Features not Covered in this Course
● Operator overloading and user defined indexers.
● Generics in depth.
● Nullable types.
● Iterators and yielding.
● LINQ and Lambda expressions.
● Dynamic typing.
● Programming of: (Web)Services, (Web)Applications with GUI and Concurrent code.
Another perception of generic types/Collections: They define a structure and some or all data types in that structure may change.
Mind that the differences between both algorithms are very small.
The definition of a Delegate type looks a little bit like a typedef in C/C++.
According Compare&lt;T&gt;():
What is the meaning of the T?
Events are like interrupts.
What are interrupts?
Interrupts are interrupting &quot;notifications&quot; issued by the hardware, e.g. I/O.
What are alternative techniques?
Primarily &quot;polling&quot;. Polling means to use software to ask for new events periodically.
The methods ReportToConsole() and DashBoardSignal() are the event handlers. Sometimes such methods are called &quot;callback functions&quot;.
Callback functions implement what we call the &quot;Hollywood principle&quot;: &quot;Don&apos;t call us, we&apos;ll call you!&quot;, they are also an incarnation of the &quot;Inversion of Control” paradigm.
We want to analyze (reflect) the type System.String.
(A good German word for reflection is &quot;Selbstauskunft&quot;.)
Iterate over its custom attributes.
Iterate over its methods.