Skip to content

Instantly share code, notes, and snippets.

@regularcoder
Last active November 7, 2016 21:15
Show Gist options
  • Save regularcoder/e1a194a32548b2520d0eaf0b9e62331e to your computer and use it in GitHub Desktop.
Save regularcoder/e1a194a32548b2520d0eaf0b9e62331e to your computer and use it in GitHub Desktop.
C# delegates
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CSharpGym
{
/// <summary>
/// Delegates (C# Programming Guide)
/// https://msdn.microsoft.com/en-us/library/ms173171.aspx
/// </summary>
public class DelegateNotes
{
//A type that represents references to methods with a particular parameter list and return type
//it can only be used at class level
public delegate int PerformCalc(int x, int y);
//event keyword lets you specify a delegate that will be called upon the occurrence of some "event" in your code
//it can only be used at class level
public event PerformCalc CalcEvent;
private int addCalc(int x, int y)
{
Console.WriteLine("Add called");
return x + y;
}
private int multCalc(int x, int y)
{
Console.WriteLine("Mult called");
return x * y;
}
public void Demo()
{
//BASICS
PerformCalc delObj = addCalc;
Console.WriteLine(delObj.Invoke(3, 5));
//Degates can be chained together
delObj += multCalc;
Console.WriteLine(delObj(4, 2));
//ANONYMOUS, LAMBDA
//C# 2.0 anoynmous methods
PerformCalc subDelAnon = delegate(int x, int y) { return x - y; };
PerformCalc subDelLambda = (x, y) => { return x - y; };
//EVENTS
if (CalcEvent != null)
{
//http://stackoverflow.com/questions/29155/what-are-the-differences-between-delegates-and-events
//An Event declaration adds a layer of abstraction and protection on the delegate instance. This protection
//prevents clients of the delegate from resetting the delegate and its invocation list
//and only allows adding or removing targets from the invocation list.
//This invocation can ONLY be done from inside this class
CalcEvent(4, 5);
}
//BEGININVOKE
IAsyncResult res = subDelAnon.BeginInvoke(9, 3, (ar) => { Console.WriteLine(ar.IsCompleted); }, null);
//Pull back BeginInvoke results
Console.WriteLine("Async result is {0}", subDelAnon.EndInvoke(res));
//DYNAMICINVOKE
//Slow as it uses reflection, unboxing, etc
object dynamicResult = subDelLambda.DynamicInvoke(new object[] { 14, 5 });
//DELEGATE VARIANCE
//https://msdn.microsoft.com/en-us/library/mt654057.aspx
FindOtherPet covarianceEx = CovariantEx;
FindOtherPet contravariantEx = ContravariantEx;
}
//Used for delegate variance examples
delegate Animal FindOtherPet(Dog a);
//Covariance permits a method to have return type that is more derived than that defined in the delegate.
//Return Dog instead of Animal
//This works because users of the delegate return value expect an Animal and Dog satisfies it
public Dog CovariantEx(Dog a)
{
return new Dog();
}
//Using Animal when delegate expects Dog return value wouldn't work as users of delegate couldn't use Dog functions
//delegate Dog FindOtherPet(Dog a);
//public Animal CovariantEx(Dog a) --> won't work
//Contravariance permits a method that has parameter types that are less derived than those in the delegate type.
//Pass in Dog instead of Animal
//This works because the delegate expects Animal and Dog satisfies it
public Animal ContravariantEx(Animal a)
{
return new Animal();
}
//Using Dog when delegate expects Animal argument won't work because when invoking delegate we could pass in another
//type of animal like Cat
//delegate Animal FindOtherPet(Animal a);
//public Animal CovariantEx(Dog a) --> won't work
}
public class Animal { }
public class Dog : Animal { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment