Is it bad to use the += operator on delegates? - c#

I just realized I don't know any C#.
Is there any difference between using += and Delegate.Combine on delegate instances?
For e.g.
public delegate void Printer(string s);
public class Program
{
public static void Main(string[] args)
{
Printer printer = new Printer((s) => { Console.WriteLine(s); });
// is it wrong to use this += operator
// on the delegate instance printer?
printer += s => {};
// And is this somewhat holier than the previous one?
// why?
Delegate.Combine(printer, new Printer((s) => {});
}
}
I ask this question because it seemed to be implied by serge karalenka's answer on this thread: https://stackoverflow.com/a/15183049/303685

Is it bad? No, not at all. In fact, I prefer it.
One good reason to use it instead of Combine() is that one is less likely to make the mistake you made in your example: failing to actually assign the result to something. I.e. note that the Combine() method returns the new delegate instance. Like string, delegates are immutable and all modifications involve creating a new instance.
While it is possible to make the same mistake with the + operator, most people would not write the code as printer + (s => {}) and even if they did, it would be pretty obvious in that case that the result of the expression was not assigned to anything. The more idiomatic += is of course immune to the problem completely. :)

Using += is perfectly fine. The language wouldn't have a bunch of special rules to make it work properly on delegates, if it was a bad thing.
It also has the advantage of working, while the second one doesn't.

Related

Using Anonymous method not preferred by .NET itself?

I am trying to learn the anonymous method and tried out this sample.
So, whenever I am trying to call WriteLog function i can just use
()=> { return "someLogData" };
The advantage is that, I need not have a separate function and can save lines of code.
public void WriteLog(Func<string> s)
{
Console.WriteLine(s);
}
But, the same does not work out with functions like
Console.WriteLine( ()=> {return "someString" } );
Why does .NET provide this anonymous method functionality but does not let to use it in one of its own kind?
There are no overloads of Console.WriteLine which accept a Func<string> - and indeed even your current WriteLog method won't do anything useful (as you'd need to invoke the delegate).
Where methods accepting specific delegates do exist - most prominently in LINQ, but elsewhere too - you can indeed use lambda expressions or anonymous methods to invoke them.
You can call Console.WriteLine using a lambda expression, but you need to cast it to a specific delegate type - as there are only conversions from lambda expressions to specific delegate or expression types, not just Delegate or object. So this will work:
Console.WriteLine((Func<string>)(() => "someLogData"));
Again though, it wouldn't be useful to do so anyway - you don't want to log the delegate, you want to log the result of invoking the delegate.
It doesn't make very much sense for Console.WriteLine to accept delegates IMO, but it would make more sense for more flexible logging, where you don't want to evaluate the string unless you're actually going to write it to a log.
Note that your WriteLog call itself can be simpler too:
WriteLog(() => "someLogData");
You need to have your anonymous method executed to get the string.
public void WriteLog(Func<string> s)
{
Console.WriteLine(s());
}
There is an advantage in this form:
public void WriteLog(Func<string> s)
{
Console.WriteLine(s);
}
let's imagine that inside it it's written as:
public void WriteLog(Func<string> s)
{
if (needToWriteLog)
{
Console.WriteLine(s);
}
}
now, let's say that you call it this way:
WriteLog(() => StringThatNeedsFiveSecondsToBuild())
and let's compare it to a similar WriteLog that only accepts a string as a parameter:
WriteLog(StringThatNeedsFiveSecondsToBuild())
The second WriteLog will always spend 5 seconds to build the string, even when needToWriteLog is false, while the first one will build it only if it's true.
Now, compare it to Console.WriteLine: Console.WriteLine will always print its content, so there is no need to use a delegate, because the 5 seconds will always be spent.
There are some methods that are similar in C#, the ones of the family Debug.* and Trace.*, but they are different. You use them like this:
Debug.WriteLine(StringThatNeedsFiveSecondsToBuild())
the trick is that they are defined like this:
[ConditionalAttribute("DEBUG")]
public static void WriteLine(string value)
so that if the DEBUG isn't defined, the whole Debug.WriteLine(StringThatNeedsFiveSecondsToBuild()) is removed, even if it had some side effects (like spending 5 seconds :-) )
All of this show something else: it's VERY important that the delegates you pass to your WriteLog AND the parameters you pass to the Debug.* and Assert.* be side effect free (clearly ignoring the time as a side effect, I mean "real" side effects like changing variable values), because you don't know if they'll really be executed.

What’s the advantage of using a delegate over making an intermediary method?

Is there a reason to use this:
bool flag;
public Form1()
{
if (flag) byDelegate = square;
else byDelegate = cube;
Text = byDelegate(3).ToString();
}
int square(int i) { return i * i; }
int cube(int i) { return i * i * i; }
delegate int delegate1(int x);
delegate1 byDelegate;
Rather than:
bool flag;
public Form2()
{
Text = fakeDelegate(3).ToString();
}
int square(int i) { return i * i; }
int cube(int i) { return i * i * i; }
int fakeDelegate(int i)
{
if (flag) return square(i);
else return cube(i);
}
Thanks.
Delegates are usually used asynchronously, for events or passed into methods/types so that the method the delegate points to ('function pointers') can be called later. In your case there looks like there's no advantage as you're doing everything synchronously.
For example
private Action<double> _performWhenFinished.
public Form1(Action<double> performWhenFinished)
{
_performWhenFinished = performWhenFinished;
}
public void CalculatePi()
{
double pie = 0d;
// Create a new thread, take 2 minutes to perform the task
// Thread.Wait etc., then and run your delegate
_performWhenFinished(pie);
}
You generally don't need to declare your own delegates in 3.5 upwards unless you want to your code to provide a bit more meaning via those declarations. The Action type and the Func type (func provides a method with a return value) save you the effort.
To address the precise situation you mentioned, you'll be over-complicating things by explicitly using a delegate, and even more if you don't really understand what's going on behind the scenes (I'm not saying you don't)...
More generally, you can think of a delegate as a "contract" (or as a "pointer to a function" if your background is in C/C++): you are telling the compiler to expect in that place a function receiving a given list of parameters and providing a given output (possibly void), but you don't tell it what the function really does. That "decouples" the method's body from the real implementation of the function, giving you the freedom to pass several different implementations from different parts of your code.
There seem to be pretty good, more elaborated explanations at this topic.
In the situation you describe I don't see any advantage to using delegates. Quite the opposite in fact since it if nothing else makes things look more complicated.
The reason to use delegates would be for example if you want to allow outside code to specify the function to call and if you don't know in advance all the functions that may be specified.
fakeDelegate is not a delegate at all: it is just a method call (that in turn calls one of two other methods).
Now, two reasons where delegates -- including lambdas and "anonymous functions" -- are very useful are:
Delegates allow a function (or method) to treated as a first-class value. The first example in the post does this, even though it is a silly example (I do this sometimes, but a larger context would be required to argue the validity of one form over the other). More often, I use this property for a data-structure that looks like IDictionary<String,MyDelegate> which is then used as map["foo"](bar) or similar -- can't do this without a big ugly dispatch (or reflection) without first-class functions values!
A /new/ delegate can create a closure -- that is, it can bind over free variables in the current lexical scope. This cannot be done with normal methods; neither cube nor square will create a closure, even though the method group is convertible to a delegate. While there is no advantage in the example above, this can be very handy when "just needing to pass that extra little bit of information" to a callback.
Since neither of these two cases are (particularly well) used in the example then....
Happy coding.

Are lambdas constructors for delegate types?

I've discovered that Rhino Mocks' AssertWasCalled fails when I use lambdas as parameters to the method being asserted.
TEST :
_mockDoer.AssertWasCalled(x => x.Print(y => Console.WriteLine("hi")));
CODE INSIDE SYSTEM UNDER TEST :
_doer.Print(y => Console.WriteLine("hi")));
This has made me think of lambdas as, effectively, constructors for delegate types.
Am I missing anything important when I think of lambdas as constructors for delegate types?
Well, they're not really "constructors" in any of the normal uses of the word "constructor".
They're expressions which can be converted to delegate types or expression tree types - the latter being essential when it comes to out-of-process LINQ.
If you're really asking whether it's expected that using two "equivalent" lambda expressions can create unequal delegate instances: yes, it is. IIRC, the C# language specification even calls out that that's the case.
However, using the same lambda expression more than once won't always create different instances:
using System;
class Test
{
static void Main(string[] args)
{
Action[] actions = new Action[2];
for (int i = 0; i < 2; i++)
{
actions[i] = () => Console.WriteLine("Hello");
}
Console.WriteLine(actions[0] == actions[1]);
}
}
On my box, that actually prints True - actions[0] and actions[1] have the exact same value - they refer to the same instance. Indeed, we can go further:
using System;
class Test
{
static void Main(string[] args)
{
object x = CreateAction();
object y = CreateAction();
Console.WriteLine(x == y);
}
static Action CreateAction()
{
return () => Console.WriteLine("Hello");
}
}
Again, this prints True. It's not guaranteed to, but here the compiler has actually created a static field to cache the delegate the first time it's required - because it doesn't capture any variables etc.
Basically this is a compiler implementation detail which you should not rely on.
Just to expand on Jon's (excellent, as always) answer: in current implementations of C#, if "the same" lambda appears in two different source code locations then the two lambdas are never realized into equal delegates. However, we reserve the right to in the future detect this situation and unify them.
Whether the converse holds or not is also implementation-dependent. If two delegates are created from a lambda at a particular source code position, the delegates might or might not have equality. There are some scenarios where it is impossible for the delegates to have equality (because they are closed over different instances of local variables, for example). In situations where it is possible for them to have equality, most of the time they do, but there are a few cases where we could perform this optimization and do not, just because the compiler is not yet sophisticated enough.

Can someone distill into proper English what a delegate is?

Can someone please break down what a delegate is into a simple, short and terse explanation that encompasses both the purpose and general benefits? I've tried to wrap my head around this and it's just not sinking in.
I have a function:
public long GiveMeTwoTimesTwo()
{
return 2 * 2;
}
This function sucks. What if I want 3 * 3?
public long GiveMeThreeTimesThree()
{
return 3 * 3;
}
Too much typing. I'm lazy!
public long SquareOf(int n)
{
return n * n;
}
My SquareOf function doesn't care what n is. It will operate properly for any n passed in. It doesn't know exactly what number n is, but it does know that n is an integer. You can't pass "Haha not an integer" into SquareOf.
Here's another function:
public void DoSomethingRad()
{
int x = 4;
long y = SquareOf(x);
Console.WriteLine(y);
}
Contrary to its name, DoSomethingRad doesn't actually do anything rad. However, it does write the SquareOf(4) which is 16. Can we change it to be less boring?
public void DoSomethingRad(int numberToSquare)
{
long y = SquareOf(numberToSquare);
Console.WriteLine(y);
}
DoSomethingRad is clearly still pretty fail. But at least now we can pass in a number to square, so it won't write 16 every time. (It'll write 1, or 4, or 9, or 16, or... zzzz still kinda boring).
It'd be nice if there was a way to change what happens to the number passed in. Maybe we don't want to square it; maybe we want to cube it, or subtract it from 69 (number chosen at random from my head).
On further inspection, it seems as though the only part of SquareOf that DoSomethingRad cares about is that we can give it an integer (numberToSquare) and that it gives us a long (because we put its return value in y and y is a long).
public long CubeOf(int n)
{
return n * n * n;
}
public void DoSomethingLeet(int numberToSquare)
{
long y = CubeOf(numberToSquare);
Console.WriteLine(y);
}
See how similar DoSomethingLeet is to DoSomethingRad? If only there was a way to pass in behavior (DoX()) instead of just data (int n)...
So now if we want to write a square of a number, we can DoSomethingRad and if we want to write the cube of a number, we can DoSomethingLeet. So if we want to write the number subtracted from 69, do we have to make another method, DoSomethingCool? No, because that takes too damn much typing (and more importantly, it hinders our ability to alter interesting behavior by changing only one aspect of our program).
So we arrive at:
public long Radlicious(int doSomethingToMe, Func<int, long> doSomething)
{
long y = doSomething(doSomethingToMe);
Console.WriteLine(y);
}
We can call this method by writing this:
Radlicious(77, SquareOf);
Func<int, long> is a special kind of delegate. It stores behavior that accepts integers and spits out longs. We're not sure what the method it points to is going to do with any given integer we pass; all we know is that, whatever happens, we are going to get a long back.
We don't have to give any parameters to SquareOf because Func<int, long> describes behavior, not data. Calling Radlicious(77, SquareOf) just gives Radlicious the general behavior of SquareOf ("I take a number and return its square"), not what SquareOf will do to any specific integer.
Now if you have understood what I am saying, then you have already one-upped me, for I myself don't really get this stuff.
* END ANSWER, BEGIN WANDERING IDIOCY *
I mean, it seems like ints could be perceived as just really boring behavior:
static int Nine()
{
return 9;
}
That said, the line between what is data and behavior appears to blur, with what is normally perceived as data is simply boring-ass behavior.
Of course, one could imagine super "interesting" behavior, that takes all sorts of abstract parameters, but requires a ton of information to be able to call it. What if it required us to provide the source code that it would compile and run for us?
Well, then our abstraction seems to have gotten us all the way back to square one. We have behavior so abstract it requires the entire source code of our program to determine what it's going to do. This is fully indeterminate behavior: the function can do anything, but it has to be provided with everything to determine what it does. On the other hand, fully determinate behavior, such as Nine(), doesn't need any additional information, but can't do anything other than return 9.
So what? I don't know.
In the simplest possible terms, it's essentially a pointer to a method.
You can have a variable that holds a delegate type (just like you would have an int variable that can hold an int type). You can execute the method that the delegate points to by simply calling your variable like a function.
This allows you to have variable functions just like you might have variable data. Your object can accept delegates from other objects and call them, without having to define all the possible functions itself.
This comes in very handy when you want an object to do things based on user specified criteria. For example, filtering a list based on a user-defined true/false expression. You can let the user specify the delegate function to use as a filter to evaluate each list item against.
A delegate is a pointer to a method. You can then use your delegate as a parameter of other methods.
here is a link to a simple tutorial.
The question I had was 'So, why would I want to do that?' You won't really 'get it' until you solve a programming problem with them.
It's interesting that no-one has mentioned one of key benefits of delegation - it's preferable to sub-classing when you realise that inheritance is not a magic bullet and usually creates more problems than it solves. It is the basis of many design patterns, most notably the strategy pattern.
A delegate instance is a reference to a method. The reason they are useful is that you can create a delegate that is tied to a particular method on a particular instance of a type. The delegate instance allows you to invoke that method on that particular instance even if the object on which you will invoke the method has left your lexical scope.
The most common use for delegate instances like this is to support the concept of callbacks at the language level.
It simply references a method. They come in great use with working with cross threading.
Here is an example right out of my code.
//Start our advertisiment thread
rotator = new Thread(initRotate);
rotator.Priority = ThreadPriority.Lowest;
rotator.Start();
#region Ad Rotation
private delegate void ad();
private void initRotate()
{
ad ad = new ad(adHelper);
while (true)
{
this.Invoke(ad);
Thread.Sleep(30000);
}
}
private void adHelper()
{
List<string> tmp = Lobby.AdRotator.RotateAd();
picBanner.ImageLocation = #tmp[0].ToString();
picBanner.Tag = tmp[1].ToString();
}
#endregion
If you didnt use a delegate you wouldn't be able to crossthread and call the Lobby.AdRotator function.
Like others have said, a delegate is a reference to a function. One of the more beneficial uses(IMO) is events. When you register an event you register a function for the event to invoke, and delegates are perfect for this task.
In the most basic terms, a delegate is just a variable that contains (a reference to) a function. Delegates are useful because they allow you to pass a function around as a variable without any concern for "where" the function actually came from.
It's important to note, of course, that the function isn't being copied when it's being bundled up in a variable; it's just being bound by reference. For example:
class Foo
{
public string Bar
{
get;
set;
}
public void Baz()
{
Console.WriteLine(Bar);
}
}
Foo foo = new Foo();
Action someDelegate = foo.Baz;
// Produces "Hello, world".
foo.Bar = "Hello, world";
someDelegate();
In most simplest terms, the responsibility to execute a method is delegated to another object. Say the president of some nation dies and the president of USA is supposed to be present for the funeral with condolences message. If the president of USA is not able to go, he will delegate this responsibility to someone either the vice-president or the secretary of the state.
Same goes in code. A delegate is a type, it is an object which is capable of executing the method.
eg.
Class Person
{
public string GetPersonName(Person person)
{
return person.FirstName + person.LastName;
}
//Calling the method without the use of delegate
public void PrintName()
{
Console.WriteLine(GetPersonName(this));
}
//using delegate
//Declare delegate which matches the methods signature
public delegate string personNameDelegate(Person person);
public void PrintNameUsingDelegate()
{
//instantiate
personNameDelegate = new personNameDelegate(GetPersonName);
//invoke
personNameDelegate(this);
}
}
The GetPersonName method is called using the delegate object personNameDelegate.
Alternatively we can have the PrintNameUsingDelegate method to take a delegate as a parameter.
public void PrintNameUsingDelegate(personNameDelegate pnd, Person person)
{
pnd(person);
}
The advantage is if someone want to print the name as lastname_firstname, s/he just has to wrap that method in personNameDelegate and pass to this function. No further code change is required.
Delegates are specifically important in
Events
Asynchronous calls
LINQ (as lambda expressions)
If you were going to delegate a task to someone, the delegate would be the person who receives the work.
In programming, it's a reference to the block of code which actually knows how to do something. Often this is a pointer to the function or method which will handle some item.
In the absolute most simplest terms I can come up with is this: A delegate will force the burdens of work into the hands of a class that pretty much knows what to do. Think of it as a kid that doesn't want to grow up to be like his big brother completely but still needs his guidance and orders. Instead of inheriting all the methods from his brother (ie subclassing), he just makes his brother do the work or The little brother does something that requires actions to be taken by the big brother. When you fall into the lines of Protocols, the big brother defines what is absolutely required, or he might give you flexibility to choose what you want to make him do in certain events (ie informal and formal protocols as outlined in Objective-C).
The absolute benefit of this concept is that you do not need to create a subclass. If you want something to fall in line, follow orders when an event happens, the delegate allows a developed class to hold it's hand and give orders if necessary.

Event and delegate contravariance in .NET 4.0 and C# 4.0

While investigating this question I got curious about how the new covariance/contravariance features in C# 4.0 will affect it.
In Beta 1, C# seems to disagree with the CLR. Back in C# 3.0, if you had:
public event EventHandler<ClickEventArgs> Click;
... and then elsewhere you had:
button.Click += new EventHandler<EventArgs>(button_Click);
... the compiler would barf because they're incompatible delegate types. But in C# 4.0, it compiles fine, because in CLR 4.0 the type parameter is now marked as in, so it is contravariant, and so the compiler assumes the multicast delegate += will work.
Here's my test:
public class ClickEventArgs : EventArgs { }
public class Button
{
public event EventHandler<ClickEventArgs> Click;
public void MouseDown()
{
Click(this, new ClickEventArgs());
}
}
class Program
{
static void Main(string[] args)
{
Button button = new Button();
button.Click += new EventHandler<ClickEventArgs>(button_Click);
button.Click += new EventHandler<EventArgs>(button_Click);
button.MouseDown();
}
static void button_Click(object s, EventArgs e)
{
Console.WriteLine("Button was clicked");
}
}
But although it compiles, it doesn't work at runtime (ArgumentException: Delegates must be of the same type).
It's okay if you only add either one of the two delegate types. But the combination of two different types in a multicast causes the exception when the second one is added.
I guess this is a bug in the CLR in beta 1 (the compiler's behaviour looks hopefully right).
Update for Release Candidate:
The above code no longer compiles. It must be that the contravariance of TEventArgs in the EventHandler<TEventArgs> delegate type has been rolled back, so now that delegate has the same definition as in .NET 3.5.
That is, the beta I looked at must have had:
public delegate void EventHandler<in TEventArgs>(object sender, TEventArgs e);
Now it's back to:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
But the Action<T> delegate parameter T is still contravariant:
public delegate void Action<in T>(T obj);
The same goes for Func<T>'s T being covariant.
This compromise makes a lot of sense, as long as we assume that the primary use of multicast delegates is in the context of events. I've personally found that I never use multicast delegates except as events.
So I guess C# coding standards can now adopt a new rule: don't form multicast delegates from multiple delegate types related through covariance/contravariance. And if you don't know what that means, just avoid using Action for events to be on the safe side.
Of course, that conclusion has implications for the original question that this one grew from...
Very interesting. You don't need to use events to see this happening, and indeed I find it simpler to use simple delegates.
Consider Func<string> and Func<object>. In C# 4.0 you can implicitly convert a Func<string> to Func<object> because you can always use a string reference as an object reference. However, things go wrong when you try to combine them. Here's a short but complete program demonstrating the problem in two different ways:
using System;
class Program
{
static void Main(string[] args)
{
Func<string> stringFactory = () => "hello";
Func<object> objectFactory = () => new object();
Func<object> multi1 = stringFactory;
multi1 += objectFactory;
Func<object> multi2 = objectFactory;
multi2 += stringFactory;
}
}
This compiles fine, but both of the Combine calls (hidden by the += syntactic sugar) throw exceptions. (Comment out the first one to see the second one.)
This is definitely a problem, although I'm not exactly sure what the solution should be. It's possible that at execution time the delegate code will need to work out the most appropriate type to use based on the delegate types involved. That's a bit nasty. It would be quite nice to have a generic Delegate.Combine call, but you couldn't really express the relevant types in a meaningful way.
One thing that's worth noting is that the covariant conversion is a reference conversion - in the above, multi1 and stringFactory refer to the same object: it's not the same as writing
Func<object> multi1 = new Func<object>(stringFactory);
(At that point, the following line will execute with no exception.) At execution time, the BCL really does have to deal with a Func<string> and a Func<object> being combined; it has no other information to go on.
It's nasty, and I seriously hope it gets fixed in some way. I'll alert Mads and Eric to this question so we can get some more informed commentary.
I just had to fix this in my application. I did the following:
// variant delegate with variant event args
MyEventHandler<<in T>(object sender, IMyEventArgs<T> a)
// class implementing variant interface
class FiresEvents<T> : IFiresEvents<T>
{
// list instead of event
private readonly List<MyEventHandler<T>> happened = new List<MyEventHandler<T>>();
// custom event implementation
public event MyEventHandler<T> Happened
{
add
{
happened.Add(value);
}
remove
{
happened.Remove(value);
}
}
public void Foo()
{
happened.ForEach(x => x.Invoke(this, new MyEventArgs<T>(t));
}
}
I don't know if there are relevant differences to regular multi-cast events. As far as I used it, it works ...
By the way: I never liked the events in C#. I don't understand why there is a language feature, when it doesn't provide any advantages.
Are you getting the ArgumentException from both? If the exception is being thrown by just the new handler, then I would think that it's backward-compatible.
BTW, I think you have your comments mixed up. In C# 3.0 this:
button.Click += new EventHandler<EventArgs>(button_Click); // old
wouldn't have run. That's c#4.0
The following code actually works if you have the delegates normalized to the same type from within upon attaching/detaching! I didn't expect detaching to work but it does. It may not be the most optimized solution but it is clean and simple and it solves a serious problem I've had with my Foundation where co-variance is important for example IObservableList : IObservableListOut. At some point extensions created different delegate types depending on context T where T can be 2 different interfaces per context and therefore the delegates created ended up of different type. It wasn't until today that I actually understood how this issue resulted. Detaching won't work with plain "- value".
private event MyEventHandler<T> happened;
public event MyEventHandler<T> Happened
{
add => this.happened += new MyEventHandler<T>(value);
remove => this.happened -= new MyEventHandler<T>(value);
}

Categories

Resources