Related
I am doing a refactor over certain code.
We have a list of investors with amounts assigned to each. The total of amounts should be equal to another total, but sometimes there are a couple of cents of difference, so we use different algorithms to assign these differences to each investor.
The current code is something like this:
public void Round(IList<Investors> investors, Enum algorithm, [here goes a list of many parameters]) {
// some checks and logic here - OMMITED FOR BREVITY
// pick method given algorithm Enum
if (algoritm == Enum.Algorithm1) {
SomeStaticClass.Algorithm1(investors, remainders, someParameter1, someParameter2, someParameter3, someParameter4)
} else if (algoritm == Enum.Algorithm2) {
SomeStaticClass.Algorithm2(investors, remainders, someParameter3)
}
}
so far we only have two algorithms. I have to implement the third one. I was given the possibility to refactor both existing implementations as well as do some generic code to make this function for future algorithms, maybe custom to each client.
My first thought was "ok, this is a strategy pattern". But the problem I see is that both algorithms receive a different parameter list (except for the first two). And future algorithms can receive a different list of parameters as well. The only thing in "common" is the investor list and the remainders.
How can I design this so I have a cleaner interface?
I thought of
Establishing an interface with ALL possible parameters, and share it
among all implementations.
Using an object with all possible parameters as properties, and use that generic object as part of the interface. I
would have 3 parameters: The list of investors, the remainders object, and a "parameters" object. But in this case, I have a similar problem. To instantiate each object and fill the required properties depends on the algorithm (unless I set all of them). I
would have to use a factory (or something) to instantiate it, using all parameters in the interface, am I right? I would be moving the problem of too many parameters to that "factory" or whatever.
Using a dynamic object instead of a statically typed object. Still
presents the same problems as before, the instantiation
I also thought of using the Visitor Pattern, but as I understand, that would be the case if I had different algorithms for different entities to use, like, another class of investors. So I don't think it is the right approach.
So far the one that convinces me the most is the second, although I am still a bit reticent about it.
Any ideas?
Thanks
Strategy has different implementations. Its straightforward when all alternate Concrete Strategies require same type signature. But when concrete implementations start asking for different data from Context, we have to gracefully take a step back by relaxing encapsulation ("breaking encapsulation" is known drawback of strategy), either we can pass Context to strategies in method signature or constructor depending upon how much is needed.
By using interfaces and breaking big object trees in to smaller containments we can restrict the access to most of the Context state.
following code demonstrates passing through method parameter.
public class Context {
private String name;
private int id;
private double salary;
Strategy strategy;
void contextInterface(){
strategy.algorithmInterface(this);
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public double getSalary() {
return salary;
}
}
public interface Strategy {
// WE CAN NOT DECIDE COMMON SIGNATURE HERE
// AS ALL IMPLEMENTATIONS REQUIRE DIFF PARAMS
void algorithmInterface(Context context);
}
public class StrategyA implements Strategy{
#Override
public void algorithmInterface(Context context) {
// OBSERVE HERE BREAKING OF ENCAPSULATION
// BY OPERATING ON SOMEBODY ELSE'S DATA
context.getName();
context.getId();
}
}
public class StrategyB implements Strategy{
#Override
public void algorithmInterface(Context context) {
// OBSERVE HERE BREAKING OF ENCAPSULATION
// BY OPERATING ON SOMEBODY ELSE'S DATA
context.getSalary();
context.getId();
}
}
Okay, I might be going in the wrong direction... but it seems kinda weird that you're passing in arguments to all the algorithms, and the identifier to which algorithm to actually use. Shouldn't the Round() function ideally just get what it needs to operate?
I'm imagining the function that invokes Round() to look something like:
if (something)
algToUse = Enum.Algorithm1;
else
if (otherthing)
algToUse = Enum.Algorithm2;
else
algToUse = Enum.Algorithm3;
Round(investors, remainder, algToUse, dayOfMonth, lunarCycle, numberOfGoblinsFound, etc);
... what if, instead, you did something like this:
public abstract class RoundingAlgorithm
{
public abstract void PerformRounding(IList<Investors> investors, int remainders);
}
public class RoundingRandomly : RoundingAlgorithm
{
private int someNum;
private DateTime anotherParam;
public RoundingRandomly(int someNum, DateTime anotherParam)
{
this.someNum = someNum;
this.anotherParam = anotherParam;
}
public override void PerformRounding(IList<Investors> investors, int remainder)
{
// ... code ...
}
}
// ... and other subclasses of RoundingAlgorithm
// ... later on:
public void Round(IList<Investors> investors, RoundingAlgorithm roundingMethodToUse)
{
// ...your other code (checks, etc)...
roundingMethodToUse.Round(investors, remainders);
}
... and then your earlier function simply looks like:
RoundingAlgorithm roundingMethod;
if (something)
roundingMethod = new RoundingByStreetNum(1, "asdf", DateTime.Now);
else
if (otherthing)
roundingMethod = new RoundingWithPrejudice(null);
else
roundingMethod = new RoundingDefault(1000);
Round(investors, roundingMethod);
... basically, instead of populating that Enum value, just create a RoundingAlgorithm object and pass that in to Round() instead.
Can I create a delegate that would behave like this?
// here I have delegate
delegate ... MyDel ...
MyDel del = SomeMethod; // or even lambda?
int number = del<int>(...);
As an idea, it's probably a duplicate question, but I'm pointing at this ->
int n = del<int>(...);
So, can a delegate be generic function? If not (and I'm pretty sure it can't), why is it implemented this way? In what cases could it be a problem?
No, a delegate instance cannot point to an open generic method.
I can only speculate why this is so, but I'd assume that the cost of this language feature does not outweigh its benefits, given that it'll probably not be used often. See Eric Lippert's answer here on how features get into C#.
Delegates do not allow such functionality; for that you need to define an interface; some examples:
interface IActOnAnything
{
void Invoke<T>(T it)
}
interface IActOnAnything<TP1>
{
void Invoke<T>(T it, TP1 p1)
}
interface IActOnAnythingByRef
{
void Invoke<T>(ref T it)
}
Unfortunately, there's no language support to facilitate implementation of such interfaces. If a class will only need to define one function which implements the interface, one could simply declare the implementation at the class level. Otherwise, one should probably declare for each implementation a nested private class which implements the interface and holds an object of its parent type.
Yes, it's possible:
public delegate int Test<T>(T input) where T : struct;
public static event Test<int> TestEvent;
static void Main(string[] args)
{
var n = TestEvent(5);
}
Yes it is possible, like Func, Action, and also you can make your own:
delegate TOutput MyDelegate<TInput,TOutput>(TInput input);
MyDelegate<string, int> myDelegate = input=>input.Length;
Also you can do this:
int n = new MyDelegate<string, int>(input => input.Length)("MY STRING"); //n=9
In my application I work with criterias. I have one base Criteria interface and and other interfaces who inherits from this base interface:
ICriteria
|
|
----------------------
| |
ITextCriteria IChoices
What I'd like to know is, what is the best way to know what Type the class is?
In my code I have a dropdown box and based on that I have to determine the type:
// Get selected criteria
var selectedCriteria = cmbType.SelectedItem as ICriteria;
if (selectedCriteria is IChoices)
{
//selectedCriteria = cmbType.SelectedItem as IChoices; Doesn't work
IChoices criteria = selectedCriteria as IChoices;//cmbType.SelectedItem as IChoices;
SaveMultipleChoiceValues(criteria);
//_category.AddCriteria(criteria);
}
else
{
//ICriteria criteria = selectedCriteria; //cmbType.SelectedItem as ICriteria;
if (selectedCriteria.GetCriteriaType() == CriteriaTypes.None)
{
return;
}
//_category.AddCriteria(criteria);
}
_category.AddCriteria(selectedCriteria);
selectedCriteria.LabelText = txtLabeltext.Text;
this.Close();
My question is, is this the best way? Or is there a better way to achieve this?
The chance is big that there are coming more interfaces based on ICriteria.
EDIT:
I have 2 types of controls which I want to add dynamically to my application. One control is a textbox and the other is a radio button.
For a radio button the user can define the options. When the options are defined, the user must choose one of the options and the chosen option must be saved in the database (this is later used to perform search operations). So, when the Save button is clicked, I have to determine the chosen type (radio or text) and save the answer possibilities (if it is a radio).
For a textbox, this doesn't have any answer possibilities. For that reason it has a different interface.
I hope I make it a little bit clearer now. Here is another question which is related: C# How to implement interface where concrete classes differs?
EDIT II:
This is how my method SaveMultipleChoiceValues looks like:
private void SaveMultipleChoiceValues(IChoices criteria)
{
foreach (DataGridViewRow row in dgvCriteriaControls.Rows)
{
if (row == dgvCriteriaControls.Rows[dgvCriteriaControls.Rows.Count - 1])
continue;
//multipleChoice.AddChoice(row.Cells["Name"].Value.ToString());
string choice = row.Cells["Name"].Value.ToString();
criteria.AddChoice(choice);
}
}
This looks like a prime example for polymorphism.
Instead of trying to do a type switch on your ICriteria implementation, why don't you add a method to ICriteria (or possibly a virtual method to some common base class of all ICriteria implementations), and just call that?
Obviously the implementation of this method would need access to objects that do not belong in your ICriteria instances, but that is a problem you can solve using other design patterns according to the specifics of your scenario.
Update:
Here's a complete solution, incorporating the code you posted:
Create a new interface ICriteriaView which models the view (in your case a Form) where ICriteria are displayed. The form needs to do some processing depending on the exact interface that criteria implement, so add a method with one overload for each interface that exists in your code. Do not add an overload for ICriteria itself. [1]
interface ICriteriaView {
void ProcessCriteria(IChoices criteria);
void ProcessCriteria(ITextCriteria criteria);
}
Your form will implement this interface, providing methods where suitable processing for each subtype of ICriteria will occur:
class MyForm : ICriteriaView {
public void ProcessCriteria(IChoices criteria) {
this.SaveMultipleChoiceValues(criteria);
}
public void ProcessCriteria(ITextCriteria criteria) {
// do nothing
}
private void SaveMultipleChoiceValues(IChoices criteria)
{
foreach (DataGridViewRow row in dgvCriteriaControls.Rows)
{
if (row == dgvCriteriaControls.Rows[dgvCriteriaControls.Rows.Count - 1])
continue;
//multipleChoice.AddChoice(row.Cells["Name"].Value.ToString());
string choice = row.Cells["Name"].Value.ToString();
criteria.AddChoice(choice);
}
}
}
Each implementation of ICriteria will need to implement a method which calls the appropriate ICriteriaView overload for its type. This is where the "redirection magic" happens: we will use polymorphism to get the compiler to "discover" the actual type of ICriteria our object is, and then use method overloading on ICriteriaView.ProcessCriteria to access the appropriate code.
interface ICriteria {
void PerformProcessingOn(ICriteriaView view);
}
interface IChoices : ICriteria {
}
interface ITextCriteria : ICriteria {
}
And this is where the dispatch to the appropriate overload happens:
class MultipleChoice : IChoices {
public PerformProcessingOn(ICriteriaView view) {
view.ProcessCriteria(this);
}
}
class SimpleInput : ITextCriteria {
public PerformProcessingOn(ICriteriaView view) {
view.ProcessCriteria(this);
}
}
Then, your code would do:
// Get selected criteria
var selectedCriteria = cmbType.SelectedItem as ICriteria;
// Here's where polymorphism kicks in
selectedCriteria.PerformProcessingOn(this);
// Finally, code that runs the same for all objects
_category.AddCriteria(selectedCriteria);
selectedCriteria.LabelText = txtLabeltext.Text;
this.Close();
Maintenance:
Whenever you add a new ICriteria sub-interface implementation, the definition of ICriteria will force you to implement the PerformProcessingOn method on it. Inside that method, all you can do really is call view.ProcessCriteria(this). In turn, this will force you to implement an appropriate ProcessCriteria overload in ICriteriaView and MyForm.
As a result, we have achieved two important objectives:
The compiler will not allow you to add a new ICriteria implementation without specifying exactly how that implementation should interact with ICriteriaView.
It is easy to discover from source code exactly what MyView does with e.g. IChoices when reading the code for MultipleChoice. The structure of the code leads you to MyForm.SaveMultipleChoiceValues "automatically".
Notes:
[1] The choice of adding an overload for ICriteria itself or not is really a tradeoff:
If you do add one, then code like this:
class MultipleChoice : IChoices {
public PerformProcessingOn(ICriteriaView view) {
view.ProcessCriteria(this);
}
}
will compile successfully always, because even if there is no ICriteriaView.ProcessCriteria(IChoices) overload there will still be the ICriteriaView.ProcessCriteria(ICriteria) overload that the compiler can use.
This means that, when adding a new ICriteria sub-interface implementation, the compiler will no longer force you to go check if the implementation of ICriteriaView.ProcessCriteria(ICriteria) really does the right thing for your new implementation.
If you do not add one, then the moment you write view.ProcessCriteria(this); the compiler will force you to go check (and update) ICriteriaView and MyForm accordingly.
In this scenario, and with the information you have provided, I believe that the appropriate choice would be the last one.
[2] As you can see above, the implementation of ICriteria.PerformProcessingOn inside MultipleChoice and SimpleInput looks exactly the same. If these two classes have a common base (which is quite possible in practice), you might be tempted to move the "duplicated" code into that base. Do not do that; it will cause the solution to break.
The tricky part is that inside MultipleChoice, when you do view.ProcessCriteria(this); the compiler can infer that the static type of this is IChoices -- this is where the redirection happens! If you move the call to ProcessCriteria inside a hypothetical base class CriteriaBase : ICriteria, then the type of this will become ICriteria and the dispatch of the call to the appropriate ICriteriaView.ProcessCriteria overload will no longer work.
You could do this:
var selectedCriteria = cmbType.SelectedItem as ICriteria;
if (typeof(IChoices).IsAssignableFrom(selectedCriteria.GetType()))
{
IChoices criteria = selectedCriteria as IChoices;
SaveMultipleChoiceValues(criteria);
}
else if(typeof(ITextCriteria).IsAssignableFrom(selectedCriteria.GetType()))
{
if (selectedCriteria.GetCriteriaType() == CriteriaTypes.None)
{
return;
}
}
But polymorphism is probably your best bet.
That is not the best way. If you are performing different actions based on the type of an object, you should probably be using polymorphism instead for a myriad number of reasons.
How you use polymorphism depends on what you actually need to have done based on the different types of ICriteria that are being used. If you just need to get a string containing all of their members, you could easily add a method to ICriteria and hand the responsibility to the class itself instead of the code that depends on it. This reduces duplication, puts code in a logical place, and makes sure you don't forget to add code for a new type of ICriteria.
If you give us more information on how you want different types to be treated/behave, we can probably give you more specific advice. :D
Here is a long term solution to an ever expanding list of critera without having to add more if/then/else.
While this code is complex to someone not used to designing in this manner, it allows you to keep your method dealing with criteria the same, and just register new delegates to handle additional criteria.
The idea is to create a map of Type objects that hold delegates in which to execute. You can then register new delegates to execute based on new Types as you generate them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Stackoverflow_4527626
{
delegate void CriteraDelegate(params object[] args);
class CriteraManager
{
private Dictionary<Type, CriteraDelegate> criterian = new Dictionary<Type, CriteraDelegate>();
public void RegisterCritera(Type type, CriteraDelegate del)
{
criterian[type] = del;
}
public void Execute(Object criteria, params object[] args)
{
Type type = criteria.GetType();
/// Check to see if the specific type
/// is in the list.
if (criterian.ContainsKey(type))
{
criterian[type](args);
}
/// If it isn't perform a more exhaustive search for
/// any sub types.
else
{
foreach (Type keyType in criterian.Keys)
{
if (keyType.IsAssignableFrom(type))
{
criterian[keyType](args);
return;
}
}
throw new ArgumentException("A delegate for Type " + type + " does not exist.");
}
}
}
interface InterfaceA { }
interface InterfaceB1 : InterfaceA { }
interface InterfaceB2 : InterfaceA { }
interface InterfaceC { }
class ClassB1 : InterfaceB1 { }
class ClassB2 : InterfaceB2 { }
class ClassC : InterfaceC { }
class Program
{
static void ExecuteCritera1(params object[] args)
{
Console.WriteLine("ExecuteCritera1:");
foreach (object arg in args)
Console.WriteLine(arg);
}
static void ExecuteCritera2(params object[] args)
{
Console.WriteLine("ExecuteCritera2:");
foreach (object arg in args)
Console.WriteLine(arg);
}
static void Main(string[] args)
{
CriteraDelegate exampleDelegate1 = new CriteraDelegate(ExecuteCritera1);
CriteraDelegate exampleDelegate2 = new CriteraDelegate(ExecuteCritera2);
CriteraManager manager = new CriteraManager();
manager.RegisterCritera(typeof(InterfaceB1), exampleDelegate2);
manager.RegisterCritera(typeof(InterfaceB2), exampleDelegate2);
manager.RegisterCritera(typeof(InterfaceC), exampleDelegate1);
ClassB1 b1 = new ClassB1();
ClassB2 b2 = new ClassB2();
ClassC c = new ClassC();
manager.Execute(b1, "Should execute delegate 2");
manager.Execute(b2, "Should execute delegate 2");
manager.Execute(c, "Should execute delegate 1");
}
}
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
When would you use delegates in C#?
The purpose of delegates
I have seen many question regarding the use of delegates. I am still not clear where and WHY would you use delegates instead of calling the method directly.
I have heard this phrase many times: "The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked."
I don't understand how that statement is correct.
I've written the following examples. Let's say you have 3 methods with same parameters:
public int add(int x, int y)
{
int total;
return total = x + y;
}
public int multiply(int x, int y)
{
int total;
return total = x * y;
}
public int subtract(int x, int y)
{
int total;
return total = x - y;
}
Now I declare a delegate:
public delegate int Operations(int x, int y);
Now I can take it a step further a declare a handler to use this delegate (or your delegate directly)
Call delegate:
MyClass f = new MyClass();
Operations p = new Operations(f.multiply);
p.Invoke(5, 5);
or call with handler
f.OperationsHandler = f.multiply;
//just displaying result to text as an example
textBoxDelegate.Text = f.OperationsHandler.Invoke(5, 5).ToString();
In these both cases, I see my "multiply" method being specified. Why do people use the phrase "change functionality at runtime" or the one above?
Why are delegates used if every time I declare a delegate, it needs a method to point to? and if it needs a method to point to, why not just call that method directly? It seems to me that I have to write more code to use delegates than just to use the functions directly.
Can someone please give me a real world situation? I am totally confused.
Changing functionality at runtime is not what delegates accomplish.
Basically, delegates save you a crapload of typing.
For instance:
class Person
{
public string Name { get; }
public int Age { get; }
public double Height { get; }
public double Weight { get; }
}
IEnumerable<Person> people = GetPeople();
var orderedByName = people.OrderBy(p => p.Name);
var orderedByAge = people.OrderBy(p => p.Age);
var orderedByHeight = people.OrderBy(p => p.Height);
var orderedByWeight = people.OrderBy(p => p.Weight);
In the above code, the p => p.Name, p => p.Age, etc. are all lambda expressions that evaluate to Func<Person, T> delegates (where T is string, int, double, and double, respectively).
Now let's consider how we could've achieved the above without delegates. Instead of having the OrderBy method take a delegate parameter, we would have to forsake genericity and define these methods:
public static IEnumerable<Person> OrderByName(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByAge(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByHeight(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByWeight(this IEnumerable<Person> people);
This would totally suck. I mean, firstly, the code has become infinitely less reusable as it only applies to collections of the Person type. Additionally, we need to copy and paste the very same code four times, changing only 1 or 2 lines in each copy (where the relevant property of Person is referenced -- otherwise it would all look the same)! This would quickly become an unmaintainable mess.
So delegates allow you to make your code more reusable and more maintainable by abstracting away certain behaviors within code that can be switched in and out.
.NET Delegates: A C# Bedtime Story
Delegates are extremely useful, especially after the introduction of linq and closures.
A good example is the 'Where' function, one of the standard linq methods. 'Where' takes a list and a filter, and returns a list of the items matching the filter. (The filter argument is a delegate which takes a T and returns a boolean.)
Because it uses a delegate to specify the filter, the Where function is extremely flexible. You don't need different Where functions to filter odd numbers and prime numbers, for example. The calling syntax is also very concise, which would not be the case if you used an interface or an abstract class.
More concretely, Where taking a delegate means you can write this:
var result = list.Where(x => x != null);
...
instead of this:
var result = new List<T>();
foreach (var e in list)
if (e != null)
result.add(e)
...
Why are delegates used if everytime I
declare a delegate, it needs a method
to point to? and if it needs a method
to point to, why not just call that
method directly?
Like interfaces, delegates let you decouple and generalize your code. You usually use delegates when you don't know in advance which methods you will want to execute - when you only know that you'll want to execute something that matches a certain signature.
For example, consider a timer class that will execute some method at regular intervals:
public delegate void SimpleAction();
public class Timer {
public Timer(int secondsBetweenActions, SimpleAction simpleAction) {}
}
You can plug anything into that timer, so you can use it in any other project or applications without trying to predict how you'll use it and without limiting its use to a small handful of scenarios that you're thinking of right now.
Let me offer an example. If your class exposes an event, it can be assigned some number of delegates at runtime, which will be called to signal that something happened. When you wrote the class, you had no idea what delegates it would wind up running. Instead, this is determined by whoever uses your class.
One example where a delegate is needed is when you have to modify a control in the UI thread and you are operating in a different thread. For example,
public delegate void UpdateTextBox(string data);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
...
Invoke(new UpdateTextBox(textBoxData), data);
...
}
private void textBoxData(string data)
{
textBox1.Text += data;
}
In your example, once you've assigned a delegate to a variable, you can pass it around like any other variable. You can create a method accepting a delegate as a parameter, and it can invoke the delegate without needing to know where the method is really declared.
private int DoSomeOperation( Operations operation )
{
return operation.Invoke(5,5);
}
...
MyClass f = new MyClass();
Operations p = new Operations(f.multiply);
int result = DoSomeOperation( p );
Delegates make methods into things that you can pass around in the same way as an int. You could say that variables don't give you anything extra because in
int i = 5;
Console.Write( i + 10 );
you see the value 5 being specified, so you might as well just say Console.Write( 5 + 10 ). It's true in that case, but it misses the benefits for being able to say
DateTime nextWeek = DateTime.Now.AddDays(7);
instead of having to define a specifc DateTime.AddSevenDays() method, and an AddSixDays method, and so on.
To give a concrete example, a particularly recent use of a delegate for me was SendAsync() on System.Net.Mail.SmtpClient. I have an application that sends tons and tons of email and there was a noticeable performance hit waiting for the Exchange server to accept the message. However, it was necessary to log the result of the interaction with that server.
So I wrote a delegate method to handle that logging and passed it to SendAsync() (we were previously just using Send()) when sending each email. That way it can call back to the delegate to log the result and the application threads aren't waiting for the interaction to finish before continuing.
The same can be true of any external IO where you want the application to continue without waiting for the interaction to complete. Proxy classes for web services, etc. take advantage of this.
You can use delegates to implement subscriptions and eventHandlers.
You can also (in a terrible way) use them to get around circular dependencies.
Or if you have a calculation engine and there are many possible calculations, then you can use a parameter delegate instead of many different function calls for your engine.
Did you read http://msdn.microsoft.com/en-us/library/ms173171(VS.80).aspx ?
Using your example of Operations, imagine a calculator which has several buttons.
You could create a class for your button like this
class CalcButton extends Button {
Operations myOp;
public CalcButton(Operations op) {
this.myOp=op;
}
public void OnClick(Event e) {
setA( this.myOp(getA(), getB()) ); // perform the operation
}
}
and then when you create buttons, you could create each with a different operation
CalcButton addButton = new CalcButton(new Operations(f.multiply));
This is better for several reasons. You don't replicate the code in the buttons, they are generic.
You could have multiple buttons that all have the same operation, for example on different panels or menus. You could change the operation associated with a button on the fly.
Delegates are used to solve an Access issue. When ever you want to have object foo that needs to call object bar's frob method but does not access to to frob method.
Object goo does have access to both foo and bar so it can tie it together using delegates. Typically bar and goo are often the same object.
For example a Button class typically doesn't have any access to the class defines a Button_click method.
So now that we have that we can use it for a whole lot things other than just events. Asynch patterns and Linq are two examples.
It seems many of the answers have to do with inline delegates, which in my opinion are easier to make sense of than what I'll call "classic delegates."
Below is my example of how delegates allow a consuming class to change or augment behaviour (by effectively adding "hooks" so a consumer can do things before or after a critical action and/or prevent that behaviour altogether). Notice that all of the decision-making logic is provided from outside the StringSaver class. Now consider that there may be 4 different consumers of this class -- each of them can implement their own Verification and Notification logic, or none, as appropriate.
internal class StringSaver
{
public void Save()
{
if(BeforeSave != null)
{
var shouldProceed = BeforeSave(thingsToSave);
if(!shouldProceed) return;
}
BeforeSave(thingsToSave);
// do the save
if (AfterSave != null) AfterSave();
}
IList<string> thingsToSave;
public void Add(string thing) { thingsToSave.Add(thing); }
public Verification BeforeSave;
public Notification AfterSave;
}
public delegate bool Verification(IEnumerable<string> thingsBeingSaved);
public delegate void Notification();
public class SomeUtility
{
public void SaveSomeStrings(params string[] strings)
{
var saver = new StringSaver
{
BeforeSave = ValidateStrings,
AfterSave = ReportSuccess
};
foreach (var s in strings) saver.Add(s);
saver.Save();
}
bool ValidateStrings(IEnumerable<string> strings)
{
return !strings.Any(s => s.Contains("RESTRICTED"));
}
void ReportSuccess()
{
Console.WriteLine("Saved successfully");
}
}
I guess the point is that the method to which the delegate points is not necessarily in the class exposing the delegate member.
Since i am new to c#, would like to know about Interfaces and Delegates in c#, the difference between them and scenarios both these to be used. Please don't provide any links, i would like an explanation in simple words.
An interface is a contract - it defines methods and properties that any implementing class has to have and as such any consumer of the interface will know they exist and can use them.
A delegate is a call back site - it defines a method signature that can invoke any method that has the same signature.
See delegates and interfaces on the C# programming guide.
An example of an interface is the IEnumerable interface. It only has one member defined - GetEnumerator. Any object that implements this interface will have this method and any code using such an object can call this method.
An example of a delegate is the Predicate<T> delegate. It is a generic delegate that is defines as following:
public delegate bool Predicate<in T>(T obj);
This means that it takes in any type T and returns a bool. Any method that takes a single type parameter and returns a bool is a match for this delegate and can be used with it.
Since delegates are also objects, they can be passed in to functions. So, any function that has a Predicate<T> delegate can pass in any mathod that matches it. Many of the Linq operators have delegates as parameters. See examples here.
A quote from C# in Nutshell.
A problem that can be solved with a delegate can also be solved with an
interface. For instance, the following explains how to solve our filter problem using
an ITransformer interface:
public interface ITransformer
{
int Transform (int x);
}
public class Util
{
public static void TransformAll (int[] values, ITransformer t)
{
for (int i = 0; i < values.Length; i++)
values[i] = t.Transform (values[i]);
}
}
class Squarer : ITransformer
{
public int Transform (int x) { return x * x; }
}
...
static void Main()
{
int[] values = { 1, 2, 3 };
Util.TransformAll (values, new Squarer());
foreach (int i in values)
Console.WriteLine (i);
}
A delegate design may be a better choice than an interface design if one or more of
these conditions are true:
The interface defines only a single
method.
Multicast capability is needed.
The subscriber needs to implement the
interface multiple times.
In the ITransformer example, we don’t need to multicast. However, the interface
defines only a single method. Furthermore, our subscriber may need to implement
ITransformer multiple times, to support different transforms, such as square or cube.
With interfaces, we’re forced into writing a separate type per transform, since Test
can implement ITransformer only once. This is quite cumbersome:
class Squarer : ITransformer
{
public int Transform (int x) { return x * x; }
}
class Cuber : ITransformer
{
public int Transform (int x) {return x * x * x; }
}
...
static void Main()
{
int[] values = { 1, 2, 3 };
Util.TransformAll (values, new Cuber());
foreach (int i in values)
Console.WriteLine (i);
}
And here is the code with delegate
public delegate int Transformer (int x);
class Util
{
public static void Transform (int[] values, Transformer t)
{
for (int i = 0; i < values.Length; i++)
values[i] = t (values[i]);
}
}
class Test
{
static void Main()
{
int[] values = { 1, 2, 3 };
Util.Transform (values, Square); // Dynamically hook in Square
foreach (int i in values)
Console.Write (i + " "); // 1 4 9
}
static int Square (int x) { return x * x; }
}
An interface can be thought of as a functional definition (or contract). In the real world, many objects have well known interfaces that make them largely (but not completely) interchangable.
For example, take a car. Once you learn how to drive a car, you learn the "Car Driving Interface". You know there will be an Accelerate() function, and a Stop() function, and typically a ShiftGears() function (even if it's just taking it out of park and putting into drive). There is also a Steer() function, and a SignalTurn() function.
There is no guarantee that any given implementation will do something the same way. For instance, a Toyota may have a "Stop()" method in it's CarDriving interface that actually calls Accelerate().
The car may support additional intefaces, such as the SeatBelt inteface, or the Radio interface. While each implementation of these objects may differ, there is always a core set of functionality that is common among all types of these objects. This allows them to be used largely interchangably without having to relearn a different interface.
Interfaces in C# are similar. Different object implementations may contain the same interface implementation, and what they do may be different, but you can treat one object that implements a specific interface the same way you treat another object that implements the same interface.
If you understand what inheritence is, then another way to think of interfaces is that they are the same as a class, but they have no implementation. So when a class inherits from another class, it inherits both that classes "inteface" and it's "implementation". If a class inherts only an interface, then it lacks an implementation and the new class must create that implementation itself.
A delegate, is completely different. A delegate is (among other things) a function pointer that is object aware. A function pointer is a variable, similar to other variables but it's type is "delegate" rather than "int" or "string". And, instead of holding data, it holds a pointer to a method (along with some state information) so that you can call different functions dynamically at run time.
In the following code, the call to "foo" is fixed. You cannot, at runtime, decide you want to call "bar" instead:
DoSometing()
{
foo();
}
If, instead you did something like the following, you can then pass different methods as arguments to your method and have it call them dynically:
DoSomething(MyFunction func)
{
MyFunction myfunc = func;
myfunc();
}
Delegats can do more than that, but that's a basic way to think of them.
OK, I can talk to you in English. You are human. I can talk to any human in English; I don't need to know all humans on earth to speak to them in English; all I care about is that they speak English.
OK, so a human is an object. English is the interface.
A lot of Humans implement the interface IEnglish!
Now apply that in a classical engineering sense. I have a car and a car battery. The car doesn't care about what type of battery, where it was made, or what shape it is.
The battery doesn't care about the car. They are functionally abstract from each other.
The battery gives power and implements the interface IBattery. The car will ONLY accept objects which implement IBattery (i.e. physical objects which are car batteries!!)
Semantically, interfaces and delegates are largely equivalent. An interface defines what an object does (methods and properties)... and a delegate defines what a particular method does. Delegates state the parameters of a function or method.... they are type safe function pointers. I'll need to have more of a think to come up with a real life example for this.
An interface is a collection of methods bound to a single object. (Side note: Objects may expose multiple interfaces, thus enabling them to exhibit multiple "personalities").
A delegate is an abstraction of a single method call. Calling a delegate has the effect of calling some other piece of code, about which the caller knows nothing.
A somewhat oversimplified view of things that nonetheless gives the flavour is to think of a delegate as a special case of an interface with exactly one method.