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.
Related
In a method that is so long that it scrolls off the screen. Just to make life easier as I program, if I want to refer to the variables of a class I can use the Me or this objects depending on which language I am using.
eg. Me.var1 = "Hello"
Is there an object (like Me) that would allow easy reference to the parameters of a function?
eg. params.par1 = "World"
There's no such feature in the language. Local variables and method arguments are treated specially by the .NET jitter, they are heavily optimized at runtime. Anything .NET would do, or you would do, to capture those variables would defeat such optimizations.
A very simple solution is to use Window + Split, it gives you two views on your code. Scroll the top one to the method header, write your code in the bottom one. You can adjust the splitter to give you more room in the bottom window.
Taking advantage of IntelliSense would be another way. Prefix the argument names with a little string, like "par". Then typing "par" in your code automatically gives you the list of argument names in the IntelliSense popup window.
These are however but band-aids for the real problem. As soon as you find yourself reaching like this, your first thought should be to split up the code in the function to make it smaller. There are some hard truths I discovered after thirty years of coding:
Long methods have more bugs. There's a metric for this, called "cyclomatic complexity". The higher the number, the more likely that the code is broken. Well supported by Visual Studio, this blog post is useful.
Code should never be indented more than 3 levels deep. By far the simplest way to discover that your cyclomatic complexity is getting out of hand without running a tool.
A method should never be larger than what fits on the screen. Any code that doesn't fit is a cognitive tax that produces compile errors and bugs. There's a corollary to this, programmers with big monitors create more bugs. The hard rule I use is one inspired by using DOS editors, a method should not have more than 25 lines of code.
Wide code produces a special kind of bug, the nasty kind that you can't see. Anything that's off the screen to the right is code that may have a bug that can take you a long time to discover. VB.NET is especially prone to this kind of bug since it uses end-of-line as a statement terminator. Much improved in VS2010 btw, the underscore is now optional in many cases. Always break your line to avoid this kind of bug.
Plan ahead and write maintainable code. Maintained code is never smaller than the original. If you already have trouble writing the original code then by definition you cannot maintain it. You have to start out small.
Always design first, code later. Long methods are a strong indicator of not thinking about code long enough before you start coding. In itself a strong bug inducer, in addition to writing correct code that just doesn't do the job.
The short answer is no. It seems like you are hoping to use this to distinguish between parameter scope and class scope for function parameters and fields with the same name, unfortunately you can't. Either use different naming schemes, or do the following:
public class MyClass {
private string myString;
private int myInt;
public MyClass(string myString) {
this.myString = myString;
}
public int DoStuff(int myInt) {
this.myInt += myInt;
return this.myInt;
}
}
to be really clear and avoid problems, you could change the names:
public class MyClass {
private string m_myString;
private int m_myInt;
public MyClass(string myString) {
m_myString = myString;
}
public int DoStuff(int myInt) {
m_myInt += myInt;
return m_myInt;
}
}
And you should really start by writing a test before the code, then you can check that you haven't accidentally mixed things up in your code.
Footnote
I include this as people coming to the title of this question may be looking for the following information.
While you say
Just for ease of programming - if I am a long way down in a function I would like to see what parameters there are without having to scroll up
In case you really want to look at your parameters from inside your code for other reasons then you need reflection. This is slow, and it's typical use would be to find a method, then reflect the parameters in that method. For a very comprehensive sample, see MSDN - ParameterInfo Class. The pertinent part of the code is:
foreach (MemberInfo mi in typeof(MyClass).GetMembers() )
{
// If the member is a method, display information about its parameters.
if (mi.MemberType==MemberTypes.Method)
{
foreach ( ParameterInfo pi in ((MethodInfo) mi).GetParameters() )
{
Console.WriteLine("Parameter: Type={0}, Name={1}", pi.ParameterType, pi.Name);
}
}
You should be able to use GetParameters() reflection method
MethodInfo barMI = bar.GetMethod("Foo");
ParameterInfo[] pars = barMI.GetParameters();
foreach (ParameterInfo p in pars)
{
Console.WriteLine(p.Name);
}
You can use this in run time. But for your aim, I would try to refactor the number of functions and their names. I try to keep code length under 80 symbols per line and the number of lines in a class under 100. Which is not always possible, but it's a good objective to decouple stuff and keep classes simple.
A simple way would be to encapsulate your parameters in an object so you can just refer to that, and intellitype (or whatever predictive feature) would show you what properties you have available without having to scroll back up. Like this
public class MyParamObject{
public string FirstParam {get;set;}
public string SecondParam {get;set;}
}
Then you could change your method from
public void MyReallyOvergrownMethod(string firstParam, string secondParam){...
to
public void MyReallyOvergrownMethod(MyParamObject params){...
then you can use the params parameter like this in the method
//Deep inside the method
if(params.FirstParam == "SomeValue"{//Do something
This is a numpty solution to a problem that would be best solved by refactoring your method. Look at loops, and conditionals and get them out into seperate private methods that are named after what they do. Loads of stuff on this, if you search for cleancoders.
In light of your comment "Just for ease of programming - if I am a long way down in a function I would like to see what parameters there are without having to scroll up": in Visual Studio, with code showing, just above the scrollbar there is a little bit you can grab and pull down to split the window. You can then have your function declaration visible in one pane and scroll as much as you like in the other. Or you can use Window menu->Split.
I've been wondering about this: would you support using simply an object as a parameter in your method? My reason behind doing this would be overloading. Currently, I'm trying to create a method that caters to many different datatypes: string, decimal, DateTime... the list goes on.
It's getting a bit messy though, so I was thinking of doing the following
public void GenericMethod(object val)
{
if (val is string)
// process as string
else if (val is decimal)
// process as decimal
else if (val is DateTime)
// do something for dt
else
// ...
}
What do you think of such a method? Would it incur unnecessary overhead? (during type checking) Have you implemented it? Tell me...
EDIT: Yeah, and just a sidenote, I'm kinda familiar with overloading. But it gets a little annoying when there are like more than 10 overloads...
Yes, that would work. However there are better ways of doing this.
Your best bet is to use overloads:
public void GenericMethod(string val)
{
// process as string
}
public void GenericMethod(decimal val)
{
// process as decimal
}
etc.
Whenever you use a is keyword in your code that's a huge hint that you're probably forgetting to use some important O.O. principles: overloads, subclasses, or the like.
Overloads aren't actually that annoying to work with, just to write. Remember, you're not coding this for yourself today, you're coding this for yourself three months from now when you have to read the code and figure out why the heck you did it that way, or where in the world that bug comes from.
Yet another reason to avoid the "switch on type" technique is for consistency with the .NET framework (and thus people's expectations). Follow Console.Write and the other wide variety of methods that are overridden within and under a given class.
I've been wondering about this: would you support using simply an object as a parameter in your method?
Very rarely. If there's a fixed set of types which are properly supported - and you'll throw an exception otherwise - then I'd use overloads.
If you can actually accept any type, and you'll handle a not-specially-supported type in some well-known way, then it's okay to accept object. That's what LINQ to XML does all over the place, and the result is a very clean API. I'd do it very carefully though - it's rarely a good idea.
And yes, there'd be an overhead. I wouldn't usually make that the basis of the decision though - the overhead will be small enough to be negligible in most cases. Design your API as cleanly as you can, then work out whether it's going to cause a bottleneck.
Yes, it would incur overhead for both type checking and boxing/unboxing the value type. I would recommend the overloads.
Another possibility, as long as you aren't doing a lot of math with the number, would be to make it a generic method. Arithmetic is rather difficult with generics though, as there are no constraints for value types which enables the use of operators.
No need of those!
Just declare as many methods with same name as you want and take each type as argument in each method.[This is called Overloading. e.g. You may have seen that +1 Overloads beside Methods, which implies that there is 1 more Method with same name but with different argument types]
Say Like this :
void Method(decimal d)
{
//Process Decimal
}
void Method(string s)
{
//Process String
}
By default, It will find its own method according to the Type.
There are cases where your approach makes sense. I've used it before, mostly when I have a bunch of processing that is the same for different data types.
But this is not overloading. Overloading would be to define different signatures for the same method name like this:
public void GenericMethod(string val)
{
// process as string
}
public void GenericMethod(decimal val)
{
// process as decimal
}
public void GenericMethod(DateTime val)
{
// do something for dt
}
// Etc.
And for some cases, this approach makes more sense.
Implementing many overloads one of them takes object is no problem. Take a look at Console.WriteLine overloads for example. http://msdn.microsoft.com/en-us/library/system.console.writeline.aspx However, take care that int for example can conflict with double:
int sum(int i, int j)
{
return i + j;
}
double sum(double i, double j)
{
return i + j;
}
object sum(object i, object j)
{
return i.ToString() + j.ToString();
}
==============================
static void Main()
{
sum(1, 2); // Error: ambigous call between `int` and `double` versions
sum(1.0, 2.0); // calls double version, although 1.0 and 2.0 are objects too
sum("Hello", "World"); // object
}
Ok, i have a need to be able to keep track of value type objects which are properties on another object, which cannot be done without having those properties implement an IObservable interface or similar. Then i thought of closures and the famous example from Jon Skeet and how that prints out 9 (or 10) a bunch of times and not an ascending order of numbers. So i thought why not do this:
Class MyClass
{
...
Func<MyValueType> variable;
...
public void DoSomethingThatGetsCalledOften()
{
MyValueType blah = variable(); //error checking too not shown for brevity
//use it
}
...
}
... in some other consuming code ...
MyClass myClass = new MyClass();
myClass.variable = () => myOtherObject.MyOtherProperty;
//then myClass will get the current value of the variable whenever it needs it
Obviously this would require some understanding of how closures work, but my question is this: is this a good idea or a dirty hack and a misuse of the closure system?
Edit: Since some people seem to be misunderstanding what i'm trying to say, here's a console program which demonstrates it:
using System;
using System.Linq;
namespace Test
{
class Program
{
public static void Main()
{
float myFloat = 5;
Func<float> test = () => myFloat;
Console.WriteLine(test());
myFloat = 10;
Console.WriteLine(test());
Console.Read();
}
}
}
That will print out 5 then 10.
You have stumbled upon the famous koan: Closures are a poor man's object. You are using Action<T> to substitute for a property getter of type T. Such a thing would be (slightly) less of a dirty trick in a more dynamic language, since it could be implemented by injecting a getter that’s decorated with your logging function, but in C# there isn’t an elegant way to monkeypatch someone’s property when they’re not expecting it.
As a mechanism for obtaining the value fro a property, it'll work (but it won't provide any mechanism for noticing updates promptly). However, it depends on how you intend to use it. To do this conveniently you'll need to use a pile of lambdas in the code, or have some DynamicMethod / Expression code do it at runtime. In most cases, something more similar to reflection would be more convenient.
I wouldn't necessarily worry about the "value type" aspect; in most cases this isn't a bottleneck, despite the FUD - and it is generally a lot easier to handle such code with object than it is via generics or similar.
I have some code in my IDE that demonstrates DynamicMethod vs raw reflection (that I intend to blog some day soon), showing how reflection-based code doesn't have to be slow (or just use HyperDescriptor).
The other option is to implement the correct interfaces / add the correct events. Perhaps via PostSharp, perhaps via dynamic types (inheriting and overriding at runtime), perhaps with regular code.
You would need to type your variable member as Func<MyValueType> (or another delegate that returns MyValueType), but you wouldn't be able to assign the value of blah in that manner. Just as with using the closure in the foreach loop above, it's only going to evaluate at a point in time. This isn't a way to keep your variable's value in sync with the other object. There is, in fact, no way to do that without either:
continuously monitoring the value of the other instance's property in some sort of loop, like a Timer
implementing a change notification event on the other instance's class
You would be able to implement a property like that (since a property is evaluated at every call), but then what's the sense in using a custom delegate, other than the fact that you don't have to know anything about the other instance.
Edit
I'll try to make this a little clearer. Using this code that you posted:
Class MyClass
{
...
Action<MyValueType> variable;
...
MyValueType blah = variable();
//use it
...
}
...
MyClass myClass = new MyClass();
myClass.variable = () => myOtherObject.MyOtherProperty;
First, for this to be functional, variable should be Func<MyValueType>, not Action<MyValueType> (Func returns a value, Action does not; since you're trying to assign a value to a variable, you need the expression to return a value).
Second, the main issue with your approach is--assuming I'm reading your code correctly--you're attempting to assign the value of the instance variable blah to the evaluated value of variable() within the class declaration. This won't work for a couple of reasons:
assignments within class declarations cannot access instance members (which variable is)
the assignment of a variable within a class declaration just occurs upon construction of the object. Even if the first condition were present, you would simply get a NullReferenceException upon instantiating your object, since it would be trying to evaluate variable, which would be null at that time
even disregarding the first two, the value of blah would still only represent the evaluated value of variable() at whatever time it was evaluated. It would not "point to" that function and be automatically kept in sync, as it seems like you're trying to do.
If you aren't looking for some sort of automatic synchronization, then there's nothing stopping you from just keeping the Func<MyValueType> delegate around to evaluate; there's nothing particularly good or bad about that approach, and it isn't a closure unless the delegate (in your case a lambda expression) involves the use of a local variable.
Consider the following example code:
static void Main(string[] args)
{
bool same = CreateDelegate(1) == CreateDelegate(1);
}
private static Action CreateDelegate(int x)
{
return delegate { int z = x; };
}
You would imagine that the two delegate instances would compare to be equal, just as they would when using the good old named method approach (new Action(MyMethod)). They do not compare to be equal because the .NET Framework provides a hidden closure instance per delegate instance. Since those two delegate instances each have their Target properties set to their individual hidden instance, they do not compare. One possible solution is for the generated IL for an anonymous method to store the current instance (this pointer) in the target of the delegate. This will allow the delegates to compare correctly, and also helps from a debugger standpoint since you will see your class being the target, instead of a hidden class.
You can read more about this issue in the bug I submitted to Microsoft. The bug report also gives an example of why we are using this functionality, and why we feel it should be changed. If you feel this to be an issue as well, please help support it by providing rating and validation.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=489518
Can you see any possible reason why the functionality should not be changed? Do you feel this was the best course of action to get the issue resolved, or do you recommend that I should take a different route?
I'm not so inclined to think this is a "bug". It appears moreover that you're assuming some behaviour in the CLR that simply does not exist.
The important thing to understand here is that you are returning a new anonymous method (and initialising a new closure class) each time you call the CreateDelegate method. It seems that you are experting the delegate keyword to use some sort of pool for anonymous methods internally. The CLR certainly does not do this. A delegate to the anonymous method (as with a lambda expression) is created in memory each time you call the method, and since the equality operator does of course compare references in this situation, it is the expected result to return false.
Although your suggested behaviour may have some benefits in certain contexts, it would probably be quite complicated to implement, and would more likely lead to unpredictable scenarios. I think the current behaviour of generating a new anonymous method and delegate on each call is the right one, and I suspect this is the feedback you will get on Microsoft Connect as well.
If you are quite insistent on having the behaviour you described in your question, there is always the option of memoizing your CreateDelegate function, which would insure that the same delegate is returned each time for the same parameters. Indeed, because this is so easy to implement, it is probably one of the several reasons why Microsoft did not consider implementing it in the CLR.
EDIT: Old answer left for historical value below the line...
The CLR would have to work out the cases in which the hidden classes could be considered equal, taking into account anything that could be done with the captured variables.
In this particular case, the captured variable (x) isn't changed either within the delegate or in the capturing context - but I'd rather the language didn't require this sort of complexity of analysis. The more complicated the language is, the harder it is to understand. It would have to distinguish between this case and the one below, where the captured variable's value is changed on each invocation - there, it makes a great deal of difference which delegate you call; they are in no way equal.
I think it's entirely sensible that this already-complex situation (closures are frequently misunderstood) doesn't try to be too "clever" and work out potential equality.
IMO, you should definitely take a different route. These are conceptually independent instances of Action. Faking it by coercing the delegate targets is a horrible hack IMO.
The problem is that you're capturing the value of x in a generated class. The two x variables are independent, so they're unequal delegates. Here's an example demonstrating the independence:
using System;
class Test
{
static void Main(string[] args)
{
Action first = CreateDelegate(1);
Action second = CreateDelegate(1);
first();
first();
first();
first();
second();
second();
}
private static Action CreateDelegate(int x)
{
return delegate
{
Console.WriteLine(x);
x++;
};
}
}
Output:
1
2
3
4
1
2
EDIT: To look at it another way, your original program was the equivalent of:
using System;
class Test
{
static void Main(string[] args)
{
bool same = CreateDelegate(1) == CreateDelegate(1);
}
private static Action CreateDelegate(int x)
{
return new NestedClass(x).ActionMethod;
}
private class Nested
{
private int x;
internal Nested(int x)
{
this.x = x;
}
internal ActionMethod()
{
int z = x;
}
}
}
As you can tell, two separate instances of Nested will be created, and they will be the targets for the two delegates. They are unequal, so the delegates are unequal too.
I don't know about the C# specific details of this problem but I worked on the VB.Net equivalent feature which has the same behavior.
The bottom line is this behavior is "By Design" for the following reasons
The first is that in this scenario a closure is unavoidable. You have used a piece of local data within an anonymous method and hence a closure is necessary to capture the state. Every call to this method must create a new closure for a number of reasons. Therefore each delegate will point to an instance method on that closure.
Under the hood a anonymous method / expression is represented by a System.MulticastDelegate derived instance in code. If you look at the Equals method of this class you will notice 2 important details
It is sealed so there is no way for a derived delegate to change the equals behavior
Part of the Equals method does a reference comparison on the objects
This makes it impossible for 2 lambda expressions which are attached to different closures to compare as equals.
I can't think of a situation where I've ever needed to do that. If I need to compare delegates I always use named delegates, otherwise something like this would be possible:
MyObject.MyEvent += delegate { return x + y; };
MyObject.MyEvent -= delegate { return x + y; };
This example isn't great for demonstrating the issue, but I would imagine that there could be a situation where allowing this could break existing code that was designed with the expectation that this is not allowed.
I'm sure there are internal implementation details that also make this a bad idea, but I don't know exactly how anonymous methods are implemented internally.
This behaviour makes sense because otherwise anonymous methods would get mixed up (if they had the same name, given the same body).
You could change your code to this:
static void Main(){
bool same = CreateDelegate(1) == CreateDelegate(1);
}
static Action<int> action = (x) => { int z = x; };
private static Action<int> CreateDelegate(int x){
return action;
}
Or, preferably, since that's a bad way to use it (plus you were comparing the result, and Action doesn't have a return value ... use Func<...> if you want to return a value):
static void Main(){
var action1 = action;
var action2 = action;
bool same = action1 == action2; // TRUE, of course
}
static Action<int> action = (x) => { int z = x; };
This is issue about LANGUAGE DESIGN.
Please do not answer to the question until you read entire post! Thank you.
With all helpers existing in C# (like lambdas, or automatic properties) it is very odd for me that I cannot pass property by a reference. Let's say I would like to do that:
foo(ref my_class.prop);
I get error so I write instead:
{
var tmp = my_class.prop;
foo(tmp);
my_class.prop = tmp;
}
And now it works. But please notice two things:
it is general template, I didn't put anywhere type, only "var", so it applies for all types and number of properties I have to pass
I have to do it over and over again, with no benefit -- it is mechanical work
The existing problem actually kills such useful functions as Swap. Swap is normally 3 lines long, but since it takes 2 references, calling it takes 5 lines. Of course it is nonsense and I simply write "swap" by hand each time I would like to call it. But this shows C# prevents reusable code, bad.
THE QUESTION
So -- what bad could happen if compiler automatically create temporary variables (as I do by hand), call the function, and assign the values back to properties? Is this any danger in it? I don't see it so I am curious what do you think why the design of this issue looks like it looks now.
Cheers,
EDIT As 280Z28 gave great examples for beating idea of automatically wrapping ref for properties I still think wrapping properties with temporary variables would be useful. Maybe something like this:
Swap(inout my_class.prop1,inout my_class.prop2);
Otherwise no real Swap for C# :-(
There are a lot of assumptions you can make about the meaning and behavior of a ref parameter. For example,
Case 1:
int x;
Interlocked.Increment(ref x);
If you could pass a property by ref to this method, the call would be the same but it would completely defeat the semantics of the method.
Case 2:
void WaitForCompletion(ref bool trigger)
{
while (!trigger)
Thread.Sleep(1000);
}
Summary: A by-ref parameter passes the address of a memory location to the function. An implementation creating a temporary variable in order to "pass a property by reference" would be semantically equivalent to passing by value, which is precisely the behavior that you're disallowing when you make the parameter a ref one.
Your proposal is called "copy in - copy out" reference semantics. Copy-in-copy-out semantics are subtly different from what we might call "ref to variable" semantics; different enough to be confusing and wrong in many situations. Others have already given you some examples; there are plenty more. For example:
void M() { F(ref this.p); }
void F(ref int x) { x = 123; B(); }
void B() { Console.WriteLine(this.p); }
If "this.p" is a property, with your proposal, this prints the old value of the property. If it is a field then it prints the new value.
Now imagine that you refactor a field to be a property. In the real language, that causes errors if you were passing a field by ref; the problem is brought to your attention. With your proposal, there is no error; instead, behaviour changes silently and subtly. That makes for bugs.
Consistency is important in C#, particularly in parts of the language that people find confusing, like reference semantics. I would want either references to always be copy-in-copy-out or never copy-in-copy-out. Doing it one way sometimes and another way other times seems like really bad design for C#, a language which values consistency over brevity.
Because a property is a method. It is a language construct responding to a pattern of encapsulating the setting and retrieval of a private field through a set of methods. It is functionally equivalent to this:
class Foo
{
private int _bar;
public int GetBar( ) { return _bar; }
public void SetBar( ) { _bar = value; }
}
With a ref argument, changes to the underlying variable will be observed by the method, this won't happen in your case. In other words, it is not exactly the same.
var t = obj.prop;
foo(ref t);
obj.prop = t;
Here, side effects of getter and setter are only visible once each, regardless of how many times the "by-ref" parameter got assigned to.
Imagine a dynamically computed property. Its value might change at any time. With this construct, foo is not kept up to date even though the code suggests this ("I'm passing the property to the method")
So -- what bad could happen if
compiler automatically create
temporary variables (as I do by hand),
call the function, and assign the
values back to properties? Is this any
danger in it?
The danger is that the compiler is doing something you don't know. Making the code confusing because properties are methods, not variables.
I'll provide just one simple example where it would cause confusion. Assume it was possible (as is in VB):
class Weird {
public int Prop { get; set; }
}
static void Test(ref int x) {
x = 42;
throw new Exception();
}
static void Main() {
int v = 10;
try {
Test(ref v);
} catch {}
Console.WriteLine(v); // prints 42
var c = new Weird();
c.Prop = 10;
try {
Test(ref c.Prop);
} catch {}
Console.WriteLine(c.Prop); // prints 10!!!
}
Nice. Isn't it?
Because, as Eric Lippert is fond of pointing out, every language feature must be understood, designed, specified, implemented, tested and documented. And it's obviously not a common scenario/pain point.