What are Interfaces and Delegates in c#? - c#

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.

Related

Using methods from a type passed as a parameter in C#

I'm working in Q#, a quantum programming language based on C#. Quantum operations become C# classes, from which you can do things like
QuantumOperation.run(simulator, param1, param2);
which will use a quantum simulator simulator to run the operation QuantumOperation with the parameters param1 and param2.
I have many different operations which I want to run using different simulators and different parameters. What I would like to do is pass the quantum operation to another method, which will iterate through all the simulators and parameters. Then I can call this method with all the quantum operations I want.
The problem is that - as far as I can tell - a quantum operation is really a class and not an object. So, for example, if I write:
static void someMethod<Qop>(){...}
then I can call this with a quantum operation QuantumOperation as:
someMethod<QuantumOperation>()
and it compiles fine. However, if I try to do something like
static void someMethod<Qop>(Qop quantumOperation){ ...}
someMethod<QuantumOperation>(quantumOperation);
I get an error of "QuantumOperation is a type, which is not valid in the given context" for the second line.
If I try:
static void someMethod<Qop>(...){
...
Qop.Run(...);
...
}
it similarly says: "'Qop' is a type parameter, which is not valid in the given context".
What seems to be happening here is that I'm passing the class as a type. But then when I want to treat the type as a class, I can't. I looked for ways to pass a class as an argument, but I only see ways to do this that will create objects in that class. But I can't use an object, since "Run" is a static method.
(I could try passing an object and getting the class from that, but (a) I don't know if it's possible to create objects of quantum operation classes, and (b) I can only find public Type GetType, which returns a type and not a class, giving the same problem).
Is there any way to pass a class as an argument, then reference static methods of that class, without ever instantiating an object?
Now, maybe I'm asking too much, since, as far as C# is concerned, it's a coincidence that all these classes have a method called "Run". It maybe shouldn't be able to attempt to call methods with the same name from different classes.
Alternatively, I could construct a method for each quantum operation and then pass those methods. The method would look like:
static void QuantumOperationWrapper(QuantumSimulator simulator, Int int_parameter){
QuantumOperation.Run(simulator, in_parameter);
}
I would need to make a new method for each quantum operation, but that's not that bad. Then I can pass this as a delegate or Func to the methods I want. The problem is that the results I want are contained in the QuantumSimulator object. So what I want to do is something like:
QuantumOperationWrapper(simulator, 3);
simulator.GetResults();
But when I do this, the results are empty. My guess is that, somehow, the simulator is being passed by value, or treated as immutable, or something that prevents QuantumOperationWrapper from altering internal parameters of the simulator.
Is there any way to I can ensure that a delegate/Func will alter the internal state of its arguments?
EDIT: I can make a delegate for the Run method, as follows:
public delegate System.Threading.Tasks.Task<Microsoft.Quantum.Simulation.Core.QVoid> RunQop(QCTraceSimulator sim, long n);
Then I can construct static void someMethod(RunQop runner, ...), and pass QuantumOperation.Run as the first argument.
However, I have the same problem, that the QCTraceSimulator I pass as an argument does not keep any of the simulation results it makes when I call this.
So if I understand you correctly you want to execute a bunch of methods with parameters on different simulators. Here is how to do this:
We first off need a List of the operations we want to perform.
var methodList = new List<Func<QCTraceSimulator, long, Task<QVoid>>>
{
QuantumOperation.Run,
// Add more methods here
}
This is a List of Funcs. A Func is a delegate type that represents a method with a parameter and a return value. Here our methods need to look like this to be able to be added to our List:
public Task<QVoid> SomeName(QCTraceSimulator sim, long parameter)
{ ...}
We also need a list of parameters you want to try this with:
var paramsList = new List<long>
{
1,
2,
-2147483648,
2147483647
};
Now we can iterate through these and run our method like so:
public void RunMethodsOnSimulator(QCTraceSimulator sim)
{
// Iterate through every method
foreach (var method in methodList)
{
// Iterate through every parameter
foreach (var parameter in paramsList)
{
// Execute the given method with the given parameter
Task<QVoid> result = method(sim, parameter);
}
}
}
You can now do whatever you want with the result. This will result in every method being called with every parameter once
Please keep in mind that this answer only solves this problem for methods that return a Task<QVoid> and take a QCTraceSimulator and a long as parameter. This solution however avoids having to modify any QuantumOperation classes (and hopefully teaches you a little about delegates)
Here is what the paramsList and the RunMethodsOnSimulator method would like with 2 or more parameters:
methodList = new List<Func<QCTraceSimulator, long, int, Task<QVoid>>>
{
QuantumOperation.Run,
// Add more methods here
}
paramsList = new List<Tuple<long, int>>
{
new Tuple<long, int>(1, 1),
new Tuple<long, int>(2, 1),
new Tuple<long, int>(1, 2),
new Tuple<long, int>(-2147483648, 1)
}
public void RunMethodsOnSimulator(QCTraceSimulator sim)
{
// Iterate through every method
foreach (var method in methodList)
{
// Iterate through every parameter
foreach (var parameter in paramsList)
{
// Execute the given method with the given parameter
Task<QVoid> result = method(sim, parameter.Item1, parameter.Item2);
}
}
}
The way the Q# simulation tests deal with this is by having a method that receives a delegate with some code you want to execute on the simulator, in particular, the simulator unittests have the RunWithMultipleSimulators method that is broadly used in places like CoreTests.cs; this is an example of how it is used:
[Fact]
public void RandomOperation()
{
Helper.RunWithMultipleSimulators((s) =>
{
Circuits.RandomOperationTest.Run(s).Wait(); // Throws if it doesn't succeed
});
}
I think you're having two separate problems: you're not getting the results back, and dealing with classes is making looping through different operations difficult. Let me try to address them separately.
Results from running an operation are returned from the Run method, not stored in the simulator. More specifically, if you invoke an operation that returns a Q# int, the return value of the Run method will be Task<long>. You can then use the value property of the task to get the actual result, or use the async/await pattern, whichever you like.
All of the operation classes can be instantiated, and they all implement the ICallable interface. This interface has an Apply method that gets passed the arguments to the operation and returns the (asynchronous) results. Each instance has to get properly instantiated with a reference to the simulator; the easiest way to do this is to call the Get generic method on the simulator instance.
If you look at SimulatorBase.cs, in the implementation of the Run method on line 101, you can see how this is done. In this method, T is the class of the operation; I is the class of the operation input; and O is the class of the operation return value. You could use basically the same code to create a list of objects that you then call Apply on with varying arguments.
I did not understand everything but from the little that I understood you can use a non static wrapper and each wrapper allows accessing to a distinct Qop static class.
static public void TestQop()
{
someMethod(new Qop1(), 0, 0, 0);
someMethod(new Qop2(), 1, 1, 1);
}
static void someMethod<T>(T qop, int simulator, int param1, int param2)
where T : QopBase
{
qop.Run(simulator, param1, param2);
}
abstract class QopBase
{
public abstract void Run(int simulator, int param1, int param2);
}
class Qop1 : QopBase
{
public override void Run(int simulator, int param1, int param2)
{
QuantumOperation1.Run(simulator, param1, param2);
}
}
class Qop2 : QopBase
{
public override void Run(int simulator, int param1, int param2)
{
QuantumOperation2.Run(simulator, param1, param2);
}
}
Calling a method on an object whose type is generically defined requires you to use a generic constraint which ensures that the used generic type defines the expected method.
At its core, this relies on polymorphism to ensure that even though the specific type can vary, it is known that all usable generic types (which can be limited via constraints) contain this specific method you wish to call.
Static classes and methods lack this feature. They cannot inherit, nor can they implement interfaces, nor can you pass them via method parameters (and trying to do it via generic is not the solution). There is no way to create an "inheritance-like" link between two static methods of two different static classes; even if the methods have the same signature otherwise.
Are there other ways? Yes. In order of preferability:
(1) The straightforward and clean solution is avoiding statics and instead use instanced classes. If you are able to do this, this is the superior option.
(2) If you can't avoid statics, you can still wrap your static in an instanced wrapper, e.g.:
public class IWrapper
{
void DoTheThing(int foo);
}
public QuantumOperationWrapper : IWrapper
{
public void DoTheThing(int foo)
{
QuantumOperationWrapper.Run(foo);
}
}
public OtherStaticOperationWrapper : IWrapper
{
public void DoTheThing(int foo)
{
OtherStaticOperationWrapper.Run(foo);
}
}
This effectively "unstatics" the static code, in a way that you can now rely on the knowledge that all your wrappers implement/inherit the common BaseWrapper and thus both implement the DoTheThing method.
Your generic method can then rely on this:
public void DoTheGenericThing<T>(T obj) where T : IWrapper
{
obj.DoTheThing(123);
}
Note: In this particular case you don't even need generics to begin with. I assume you don't really need generics in this case, but since the answer can apply to both generic and non-generic cases, I've left the generic parameter in the solution. There may be specific cases in which you still need to use generics, though I suspect this is not one of them.
(3) A third but very dirty option is to use reflection to call the method anyway and just assume you never pass in a type which does not have the expected static method. But this is a really bad practice approach which will be fraught with bugs, it will be nigh impossible to debug, and it's absolutely not refactor-friendly.
Maybe you can try to deal with the situation using Interfaces. Something like that:
public interface IQuantumOperation
{
void Run();
void Run(MyFancyClazz simulator, MyFancyParam param1, MyFancyParam param2);
//And other possible methods
}
Then you can make use of this Interface as a type parameter's contract
static void someMethod<Qop>(Qop myQopParameter) where Qop : IQuantumOperation
{
...
//Now you can call your Run method
myQopParameter.Run(...);
...
//Or other fancy Run method with parameters like below
myQopParameter.Run(simulator, param1, param2);
}
Finally make sure that your QuantumOperation class implements the IQuantumOperation interface

Call any class sharing the same method name in C#

I have a significant number of classes which share the same method name, but don not share a common base/interface. I cannot touch these classes, however, can I call the method irrespective of the defining class?
Eg:
Namespace n1: class A { void M1(n1.CustObj ob1){} }
Namespace n2: class B { void M1(n2.CustObj ob1){} }
Would it be possible to abstract from these common methods/parameters, like so?
method(Object obj)
{
obj.M1(new CustObj() {
x = 3;
}); // CustObj can either belong to n1 or n2
}
You have a number of classes, each of which has a method, with the same name, but with a different signature. The identical method names are a red herring here therefore as they are different methods.
This therefore rules out using dynamic or reflection to provide a single method that can handle all of them, unless you then hard-code tests for each type within the one method, or take Jonathan Wood's approach of passing in an existing instance of CustObj via a dynamic parameter too.
One solution might be to create extension methods for each type:
public void Method(this A obj)
{
obj.M1(new n1.CustObj()
{
x = 3
});
}
public void Method(this B obj)
{
obj.M1(new n2.CustObj()
{
x = 3
});
}
and so on. Then at least you can do someObj.Method(); on A, B and so forth.
You could use either the dynamic keyword or reflection.
Of the two, I prefer dynamic. However, since your constructor argument is also a different type you'd need to do something like this:
void method(dynamic obj, dynamic arg)
{
arg.x = 3;
obj.M1(arg);
}
I understand it's unlikely that your code is set up to do this but you haven't shown much of how your method is used. And in the end, this might be the best you can do if you're unable to modify the existing classes.

C# how delegates and interfaces can play a role in this example

I would like to understand if/when to use delegates and interfaces in my code. The structure is pretty simple. The main class initialize a windows form:
class MainClass
{
public static void Main()
{
InputForm InputForm1 = new InputForm();
InputForm1.ShowDialog(); // show interface to prompt user
}
}
And the class for the form has a button and few more methods:
public partial class InputForm : Form
{
public InputForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// do some calculation and then create a dictionary of items
for (int n = 1; n <= dict.Count; n++) // loop through items
{
dict[n].calculatedLength = theLength.calcLength(arg1, arg2, dict[n].speed);
}
}
}
When the button is clicked, the program does some calculation (calling methods in the same class InputForm) and save results into a dictionary (dict). Each element is an animal and I have some properties that I store in the dictionary (e.g. under the key "Dog" I have an average weight of dogs, an average speed, etc.).
Using the speed and two default arguments (arg1 that is the number of hours and arg2 that is the number of minutes) I have to call the method of the class LengthClass in order to get the estimated length that is covered by the specific animal in arg1 hours and arg2 minutes.
The LengthClass is like this:
class LengthClass
{
static double calcLength(double arg1, double arg2, double speed)
{
// do some calculation
return x;
}
}
Now the question: is there space in this example to use delegates and interfaces? Can you please show me how to best do it and what are the advantages/disadvantages in doing so instead of calling the calcLength method directly as I'm doing?
EDITED: I included the Microsoft guideline
Microsoft Guideline
Both delegates and interfaces enable a class designer to separate type declarations and implementation. A given interface can be inherited and implemented by any class or struct. A delegate can be created for a method on any class, as long as the method fits the method signature for the delegate. An interface reference or a delegate can be used by an object that has no knowledge of the class that implements the interface or delegate method. Given these similarities, when should a class designer use a delegate and when should it use an interface?
Use a delegate in the following circumstances:
An eventing design pattern is used.
It is desirable to encapsulate a static method.
The caller has no need to access other properties, methods, or
interfaces on the object implementing the method.
Easy composition is desired.
A class may need more than one implementation of the method.
Use an interface in the following circumstances:
There is a group of related methods that may be called.
A class only needs one implementation of the method.
The class using the interface will want to cast that interface to
other interface or class types.
The method being implemented is linked to the type or identity of the
class: for example, comparison methods.
The original answer (What I think)
Interfaces and delegates were made to make things easier when two classes have the same proprieties/behaviours.
I think that if you had something like that
private void Button(object sender, EventArgs e)
{
List<IAnimal> animals = Farm.GetAnimals();
foreach(IAnimal animal in animals)
{
dict[animal.name] = LeghtClass.CalculateLenght(animal);
//dict[animal.name] = animal.CalculateOwnLenght(); //using a method in the interface
}
}
You wouldn't have to worry about passing the method its parameters (wichh would help you when refactoring).
interface IAnimal
{
double Hours;
double Minutes;
double GrowSpeed;
//void CalculateOwnLenght();
}
And your lenght class would calculate it like that:
class LengthClass
{
static double calcLength(IAnimal animal)
{
return (animal.Hours + animal.Minutes / 60) * animal.GrowSpeed;
}
}
I can't think how delegates would help you unless if you do something like that:
foreach(var animal in animals)
{
delegate = animal.CalculateOwnLeght;
dict[animal.name] = delegate();
}
Ok, I have shown some code without saying anything.
I think interfaces are useful if you use them in more than one place, otherwise it can be messy - you just repeat youself more when using interfaces.
I personally don't think your way is wrong but I've read people saying that static is bad practise without proving why in a way I could understand, the one thing I remember is that it gets confusing easily and uses more resources.
I'd use delegates when I have to point to some method but I don't know the object of untill the code is running (they don't have mush use for this case, I think).
delegate void Cry();
...
cat = new Cat(); dog = new Dog();
...
foreach(var animal in animals)
{
if (animal is Cat)
{
Cry = cat.meow;
}
else if (animal is Dog)
{
Cry = dog.bark;
}
else {...}
if (animal.isInPain)
{
Cry();
}
}

Does new 'dynamic' variable type in .NET 4.0 solve the single/multiple method dispatch issue in CLR?

The problem of single dispatch is mostly familiar to people engaged in coding with statically typed languages like Java and C#. The basic idea is:
While the runtime polymorphism allows us to dispatch to the right method call according to the type (runtime type) of receiver, for example:
IAnimal mything = new Cat();
mything.chop();
The method call will be performed according to the runtime type of mything, namely Cat.
This is the single dispatch capability (which is present in Java/C#).
Now, if you need to dispatch not only on the runtime type of receiver, but on the types of (multiple) arguments either, you face a little problem:
public class MyAcceptor {
public void accept (IVisitor vst) {...}
public void accept (EnhancedConcreteVisitor vst) {...}
}
The second method never gets called, because in our 'consumer' code we just tend to treat different types of objects (visitors in my example) by their common supertype or interface.
That's why I ask - because dynamic typing allows the multiple dispatch polymorphism and C# 4.0 has that dynamic keyword ;)
Yes, dynamic typing allows multiple dispatch - and no, you don't have to create your own dynamic object to do it.
Suppose we wanted to implement Enumerable.Count() ourselves, and we didn't want a load of "if (source is IList)" tests in our code. We could write it like this:
public static class Enumerable
{
public static int Count<T>(this IEnumerable<T> source)
{
dynamic d = source;
return CountImpl(d);
}
private static int CountImpl<T>(ICollection<T> collection)
{
return collection.Count;
}
private static int CountImpl(ICollection collection)
{
return collection.Count;
}
private static int CountImpl<T>(string text)
{
return text.Length;
}
private static int CountImpl<T>(IEnumerable<T> source)
{
// Fallback
int count = 0;
foreach (T t in source)
{
count++;
}
return count;
}
}
I'm not saying it would be a good idea, but that's how it would work :)
Note that you need to be careful not to introduce situations where you could end up with an ambiguous call for some types. This wouldn't be an issue using classes for parameters, but consider that a single class can implement multiple interfaces.
Yes, you can create DLR types that do arbitrarily complex dispatch. Check out http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

c# delegate and abstract class

I currently have 2 concrete methods in 2 abstract classes. One class contains the current method, while the other contains the legacy method. E.g.
// Class #1
public abstract class ClassCurrent<T> : BaseClass<T> where T : BaseNode, new()
{
public List<T> GetAllRootNodes(int i)
{
//some code
}
}
// Class #2
public abstract class MyClassLegacy<T> : BaseClass<T> where T : BaseNode, new()
{
public List<T> GetAllLeafNodes(int j)
{
//some code
}
}
I want the corresponding method to run in their relative scenarios in the app. I'm planning to write a delegate to handle this. The idea is that I can just call the delegate and write logic in it to handle which method to call depending on which class/project it is called from (at least thats what I think delegates are for and how they are used).
However, I have some questions on that topic (after some googling):
1) Is it possible to have a delegate that knows the 2 (or more) methods that reside in different classes?
2) Is it possible to make a delegate that spawns off abstract classes (like from the above code)? (My guess is a no, since delegates create concrete implementation of the passed-in classes)
3) I tried to write a delegate for the above code. But I'm being technically challenged:
public delegate List<BaseNode> GetAllNodesDelegate(int k);
GetAllNodesDelegate del = new GetAllNodesDelegate(ClassCurrent<BaseNode>.GetAllRootNodes);
I got the following error:
An object reference is required for the non-static field, method, property ClassCurrent<BaseNode>.GetAllRootNodes(int)
I might have misunderstood something... but if I have to manually declare a delegate at the calling class, AND to pass in the function manually as above, then I'm starting to question whether delegate is a good way to handle my problem.
Thanks.
The way you're attempting to use delegates (constructing them with new, declaring a named delegate type) suggests that you're using C# 1. If you're actually using C# 3, it's much easier than that.
Firstly, your delegate type:
public delegate List<BaseNode> GetAllNodesDelegate(int k);
Already exists. It's just:
Func<int, List<BaseNode>>
So you don't need to declare your own version of it.
Secondly, you should think of a delegate as being like an interface with only one method in it, and you can "implement" it on the fly, without having to write a named class. Just write a lambda, or assign a method name directly.
Func<int, List<BaseNode>> getNodesFromInt;
// just assign a compatible method directly
getNodesFromInt = DoSomethingWithArgAndReturnList;
// or bind extra arguments to an incompatible method:
getNodesFromInt = arg => MakeList(arg, "anotherArgument");
// or write the whole thing specially:
getNodesFromInt = arg =>
{
var result = new List<BaseNode>();
result.Add(new BaseNode());
return result;
};
A lambda is of the form (arguments) => { body; }. The arguments are comma-separated. If there's only one, you can omit the parentheses. If it takes no parameters, put a pair of empty parentheses: (). If the body is only one statement long, you can omit the braces. If it's just a single expression, you can omit the braces and the return keyword. In the body, you can refer to practically any variables and methods from the enclosing scope (apart from ref/out parameters to the enclosing method).
There's almost never any need to use new to create a delegate instance. And rarely a need to declare custom delegate types. Use Func for delegates that return a value and Action for delegates that return void.
Whenever the thing you need to pass around is like an object with one method (whether an interface or a class), then use a delegate instead, and you'll be able to avoid a lot of mess.
In particular, avoid defining interfaces with one method. It will just mean that instead of being able to write a lambda to implement that method, you'll have to declare a separate named class for each different implementation, with the pattern:
class Impl : IOneMethod
{
// a bunch of fields
public Impl(a bunch of parameters)
{
// assign all the parameters to their fields
}
public void TheOneMethod()
{
// make use of the fields
}
}
A lambda effectively does all that for you, eliminating such mechanical patterns from your code. You just say:
() => /* same code as in TheOneMethod */
It also has the advantage that you can update variables in the enclosing scope, because you can refer directly to them (instead of working with values copied into fields of a class). Sometimes this can be a disadvantage, if you don't want to modify the values.
You can have a delegate that is initialized with references to different methods depending on some conditions.
Regarding your questions:
1) I'm not sure what you mean under "knows". You can pass any method to the delegate, so if you can write method that "knows" about some other methods than you can do a similar delegate.
2) Again, delegates can be created from any method that can be executed. For example if you have an initialized local variable of type ClassCurrent<T> you can created delegate for any instance method of type ClassCurrent<T>.
3) Delegate can call only the method that actually can be called. I mean that you cannot call ClassCurrent.GetAllRootNodes because GetAllRootNodes is not a static method, so you need an instance of the ClassCurrent to call it.
The delegate can stay in any class that has access to the ClassCurrent and MyClassLegacy.
For example you can create smth like:
class SomeActionAccessor<T>
{
// Declare delegate and fied of delegate type.
public delegate T GetAllNodesDelegate(int i);
private GetAllNodesDelegate getAllNodesDlg;
// Initilaize delegate field somehow, e.g. in constructor.
public SomeActionAccessor(GetAllNodesDelegate getAllNodesDlg)
{
this.getAllNodesDlg = getAllNodesDlg;
}
// Implement the method that calls the delegate.
public T GetAllNodes(int i)
{
return this.getAllNodesDlg(i);
}
}
The delegates can wrap both static and instance method. The only difference is that for creation delegate with instance method you need instance of the class who owns the method.
Let both ClassCurrent and MyClassLegacy implement an interface INodeFetcher:
public interface INodeFetcher<T> {
List<T> GetNodes(int k);
}
For ClassCurrent call the GetAllRootNodes method from the interface's implementation and for MyLegacyClass the GetAllLeaveNodes method.
Why would you want a delegate for this? It sounds overly complex. I would just create a method in a new class that you could instansiate when you needed to call you method. This class could be given some context information to help it decide. Then I would implement logic in the new method that would decide whether to call the current method or the legacy method.
Something like this:
public class CurrentOrLegacySelector<T>
{
public CurrentOrLegacySelector(some type that describe context)
{
// .. do something with the context.
// The context could be a boolean or something more fancy.
}
public List<T> GetNodes(int argument)
{
// Return the result of either current or
// legacy method based on context information
}
}
This would give you a clean wrapper for the methods that is easy to read and understand.
As a variation of the theme suggested by Rune Grimstad I think you could use the strategy pattern (e.g.
Introduction to the GOF Strategy Pattern in C# ).
This would be especially interesting in the case where you cannot change the LegacyClass (and therefore maybe cannot easily use the "interface approach" suggested by Cornelius) and if you are using dependency injection (DI; Dependency injection). DI would (maybe) let you inject the correct implementation (concrete strategy) in the right place.
Strategy:
public interface INodeFetcher<T> {
List<T> GetNodes(int k);
}
Concrete Strategies:
public class CurrentSelector<T> : INodeFetcher<T>
{
public List<T> GetNodes(int argument)
{
// Return the result "current" method
}
}
public class LegacySelector<T> : INodeFetcher<T>
{
public List<T> GetNodes(int argument)
{
// Return the result "legacy" method
}
}
-> Inject/instantiate the correct concrete strategy.
Regards

Categories

Resources