Delegate Questions - c#

I am new to C# and have two questions about delegates.
MSDN shows that the Delegate class only has two constructors, both which take two arguments each. However, in the program below, I am instantiating a Delegate object with a seemingly one-parameter constructor (see the commented line).
using System;
static class Program
{
public delegate void MyDelegate();
static void MyMethod()
{
Console.WriteLine("I'm inside MyMethod!");
}
static void Main()
{
MyDelegate myDelegate = new MyDelegate(MyMethod); // Constructor Call
myDelegate();
}
}
Am I misunderstanding something?
My second question is: when declaring delegates with one or more parameters, why do we need to give the parameters names? In C++, we could do something like this inside classes:
public delegate void MyOtherDelegate(int, int, string);

It may look like you're calling a standard constructor, but the C# compiler is actually doing a little slight of hand with your code. When you write
MyDelegate myDelegate = new MyDelegate(MyMethod);
You're not actually invoking any of the constructors listed on MSDN directly. It instead calls a constructor that the compiler has automatically defined on the delegate type MyDelegate (these constructors are not shown on MSDN). In fact, the constructors that are listed on MSDN cannot even be called directly:
This constructor cannot be used in application code. To create a delegate by specifying the name of an instance method, use an overload of the CreateDelegate method…
It's worth noting that you can even do this for brevity:
MyDelegate myDelegate = MyMethod;
As for why parameter names are necessary, perhaps they may not be strictly necessary for compilation in general, but I suspect that the designers of the CLR wanted to be consistent with other features of the in the run-time. It allows you to do things like specifying explicit parameter names that you wouldn't be able to do otherwise:
Func<int, int> foo = x => x + 1;
foo(arg: 1);
It also means you can inspect the parameter names through reflection and potentially do some useful processing with them.

Not exactly answering your question but just so you are aware, C# also supports Func delegates. in which case you don't need to even declare anything.
e.g. This method accepts a delegate with a parameter of type string and output of Int
public static void DoSomethingWithDelegate(Func<string, Int32> converstionDelegate)
{
int x = converstionDelegate("1");
}
Read more about it here: http://msdn.microsoft.com/en-us/library/bb549151.aspx

Related

How to possibly extend a generic delegate type with a non-generic one in C#?

I would like to define a non-generic delegate extending a generic delegate to define a default for the generic delegate type parameter, i.e. something like this (not a valid piece of C# code but an obvious-to-understand illustration for the concept I mean hopefully):
public delegate void MyDelegate<T>(T arg);
public delegate void MyDelegate(object arg) : MyDelegate<object>;
What is, if any, the correct way to declare this?
Needless to say I can just declare 2 independent delegates to achieve virtually same effect a way like this:
public delegate void MyDelegate<T>(T arg);
public delegate void MyDelegate(object arg);
but I'd like to do to make the actual relation between them (the fact a bare MyDelegate type is meant to equal MyDelegate<object>, the way like a class extending another class or literally) definite and make the following code will become valid if possible:
MyDelegate<object> d1;
MyDelegate d2;
MyDelegate d1 = d2;
Sorry, I may have been too harsh in saying you should know delegate types are sealed. It is clear in the specification, but I took a look at the latest version of the MSDN language documentation, and it does not seem to mention this at all. Well, anyway…they are sealed. 😊 You can't create a new class that inherits a delegate type, and you certainly can't use the delegate keyword to declare a new delegate type that inherits another delegate type (the keyword has a very specific syntax, and doesn't even allow an inheritance syntax).
It's still not really clear to me what you're trying to do. But, in some sense, a delegate type is an interface with just one member. It's more flexible, of course, because the implementation isn't in a single type, but can be any method from any type. But conceptually, the two are very similar.
In that sense, you could express your intent in code using an interface instead of a delegate. For example:
interface IDelegate<T>
{
void M(T arg);
}
interface IDelegateObject : IDelegate<object> { }
Of course, the problem with this is that now you need some type that will implement the interface in question. Any given type will only be able to implement any given interface once, so you lose a lot of the flexibility that delegate types would ordinarily give you.
But, you can do something like this:
IDelegate<object> d1;
IDelegateObject d2;
d1 = d2;
That is, since IDelegateObject inherits IDelegate<object>, and thus "is a" IDelegate<object>, you can then assign a value of type IDelegateObject, i.e. d2, to a variable of type IDelegate<object>, i.e. d1.

How to add methods to the invocation list of a delegate without instantiating the delegate?

I have to add multiple methods to the invocation list of a delegate. However, all of them have decision logic associated with them. So, there's an if block before the method gets attached to the invocation list of the delegate. Can I do this without instantiating the delegate. The code snippet looks like the following:
public delegate void SomeDelegate();
static void Method1() {}
static void Method2() {}
static void AddMethodsToInvocationList()
{
SomeDelegate someDelegate = new SomeDelegate();
if (someLogic1) someDelegate += Method1;
if (someLogic2) someDelegate += Method2;
}
Basically, I wish to be able to create an instance of the delegate without passing any methods as parameters. However I get a compiler error with "does not contain a constructor that takes 0 arguments" error, if I try and instantiate the delegate without passing any methods as parameters.
I would also be open to solving this issue a different way if someone else has a better way of doing it. However, delegates have to be used.
Thank you for any help. Much appreciated.
You can simply initialize it to null. That is the idiomatic value for a multicast delegate that doesn't have any operations added to it.

C# function that takes pointer to function as an in parameter without declaring any specific delegate types?

I want to implement a method that will find stuff in my custom class. It should work like generic collections work - i pass a pointer to a function, and the method will iterate through all it has to look in, apply this function, and if it returns true return the found item.
I'd like to pass function pointer as a parameter, but i dont want to declare delegate types.
I know i can do something like:
delegate bool Foo(MyClass)
MyClass MyMethod(Foo x)
{...}
And i know i can do something like this:
MyClass MyMethod(Func<MyClass,bool> x)
But can i do it without declaring a delegate type and without using built in stuff like Func<> which has limits on how many parameters i can have (in case of Func, one...)
You can just use delegate if you want, although it's a bit old school :)
public void TestInvokeDelegate()
{
InvokeDelegate( new TestDelegate(ShowMessage), "hello" );
}
public void InvokeDelegate(TestDelegate del, string message)
{
del(message);
}
public delegate void TestDelegate(string message);
public void ShowMessage(string message)
{
Debug.WriteLine(message);
}
You can allways pass in a Delegate and call DynamicInvoke on it:
MyClass MyMethod(Delegate x) {
// ...
x.DynamicInvoke(....);
// ...
}
It looks like you are trying to implement the Visitor pattern. In this case visiting methods usually have only one parameter - the instance to visit. Having additional arguments passed around conceals the use of the pattern and makes it harder to reason about. This article shows you one way to implement it in C#.
The key is to create a visitor class that will encapsulate all the parameters that affect the visiting process. This way you don't need to pass anythnig other than an object in question in the visiting method - everything else lives in instance fields.
However, if you really want to pass some additional parameters in the method and don't know what type they can have, there are ways to do that. More or less standard approach in .NET world is to use a delegate without return value and with single parameter of type object, the example would be ParameterizedThreadStart delegate:
public delegate void ParameterizedThreadStart(
Object obj
)
This way you get to pass only one parameter in the delegate, but it could be anything - an instance of a class, an array or null, if you end up not needing additional arguments after all. The downside of this approach is that it requires type casting which can lead to runtime errors.

How are extension methods compiled?

How the C# compiler implement extension methods?
The process is exactly the same as overload resolution:
Func(myObject);
The compiler checks all functions named "Func" and tries to match the static type of myObject to the parametrs (possibly using conversions, upcasting to base class). If it succeeds, then calls the appropriate function.
If you realize that you can call extensions methods "in a normal way", then it clears up:
static class MyExtensions
{
public static void MyFunc(this string arg)
{
// ...
}
}
string a = "aa";
MyExtensions.MyFunc(a); // OK
a.MyFunc(); // same as above, but nicer
For the given type (here string), the compiler just looks for all static functions with "this" modifier on the first argument and tries to match the static type on the left of the . (in this example "a") with the parameter type in the function.
Instance methods of a class have a hidden argument. An example:
class Example {
public void Foo(int arg) {}
}
actually looks like this when the JIT compiler is done with it, converted back to C# syntax:
static void Foo(Example this, int arg) {}
That hidden argument is the reason that you can use this in an instance method. The JIT compiler figures out the argument to pass from the object reference you provide to call the Foo method.
As you can tell, it is now a very short hop to an extension method.
The compiler first looks in the base class for a function matching the signature of the function. If it can't find it than it looks for an extension. If an extension has the same signature as a base class method than the base class method is called instead.
This might help:
Extension Methods

contravariance seem to cause a conflicted behavior

The following example is taken from C# in Depth: What you need to master C# 2 and 3, and seems to only only cause a breaking change as jskeet has identified, but be wrong. Please explain:
delegate void SampleDelegate(string x);
public void CandidateAction (string x)
{
Console.WriteLine("Snippet.CandidateAction")
}
public class Derived: Snippet
{
public void CandidateAction (object x)
{
Console.WriteLine("Derived.CandidateAction")
}
}
....
Derived x = new Derived();
SampleDelegate factory = new SampleDelegate (x.CandidateAction);
factory ("test");
Now, why should it work altogether as SampleDelegate accept string not the object. And to my knowledge, object doesn't derive from the string. It is the other way around. That's what contravariance permits under c# 2.0. The seems to demonstrate the opposite effect.
Conceptually, Derived.CandidateAction's signature is saying, "I can handle any object you want to throw at me." SampleDelegate's contract is "You have to be able to handle a string." Now if a method can handle any object, it can certainly handle a string. So Derived.CandidateAction is capable of fulfilling what SampleDelegate needs, and can therefore be assigned to a SampleDelegate variable.
I wrote a more detailed discussion of this (admittedly from a C# 4 point of view) at http://hestia.typepad.com/flatlander/2008/12/c-covariance-and-contravariance-by-example.html.
Contravariance allows you to use a method which has parameters which are a base type of the parameters in the delegate method signature.
The delegate signature defines what types will be passed to the method. The method itself can have types that are less "specific". In your example, when the delegate is invoked as string is being passed. It is perfectly ok for the actual method to only want an object because a variable of type object is allowed to hold an instance of type string.
This is most useful in event handling scenarios where you can write an event handler like this that can be attached to almost any event (even when the args parameter being passed is more specific like ItemCheckedEventArgs):
public void GenericHandler(object source, EventArgs args) {
//do something generic
}

Categories