Why Can't an Anonymous Method Be Assigned to Var

Why can't an anonymous method be assigned to var?

UPDATE: This answer was written over ten years ago and should be considered to be of historical interest; in C# 10 the compiler will infer some delegate types.


Others have already pointed out that there are infinitely many possible delegate types that you could have meant; what is so special about Func that it deserves to be the default instead of Predicate or Action or any other possibility? And, for lambdas, why is it obvious that the intention is to choose the delegate form, rather than the expression tree form?

But we could say that Func is special, and that the inferred type of a lambda or anonymous method is Func of something. We'd still have all kinds of problems. What types would you like to be inferred for the following cases?

var x1 = (ref int y)=>123;

There is no Func<T> type that takes a ref anything.

var x2 = y=>123;

We don't know the type of the formal parameter, though we do know the return. (Or do we? Is the return int? long? short? byte?)

var x3 = (int y)=>null;

We don't know the return type, but it can't be void. The return type could be any reference type or any nullable value type.

var x4 = (int y)=>{ throw new Exception(); }

Again, we don't know the return type, and this time it can be void.

var x5 = (int y)=> q += y;

Is that intended to be a void-returning statement lambda or something that returns the value that was assigned to q? Both are legal; which should we choose?

Now, you might say, well, just don't support any of those features. Just support "normal" cases where the types can be worked out. That doesn't help. How does that make my life easier? If the feature works sometimes and fails sometimes then I still have to write the code to detect all of those failure situations and give a meaningful error message for each. We still have to specify all that behaviour, document it, write tests for it, and so on. This is a very expensive feature that saves the user maybe half a dozen keystrokes. We have better ways to add value to the language than spending a lot of time writing test cases for a feature that doesn't work half the time and doesn't provide hardly any benefit in cases where it does work.

The situation where it is actually useful is:

var xAnon = (int y)=>new { Y = y };

because there is no "speakable" type for that thing. But we have this problem all the time, and we just use method type inference to deduce the type:

Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });

and now method type inference works out what the func type is.

Why is it useful to have an anonymous function stored as a variable, and pass it to higher order functions?

The brackets are only there when you're calling the function. If you pass the call with the brackets into the .filter() method, you'll actually be passing the result of the call, rather than a pointer to the call itself. The alternative is to pass in the entire function into the filter function, but readability tends to suffer. It also limits your ability to modify what's going into the function you're putting it in.

Imagine a case where you might want to do a sort instead of a filter, and you wanted to change the sort based on a boolean passed in.

Take this basic sort for example:

var numbers = [4, 2, 5, 1, 3];

numbers.sort(function(a, b) {
return a - b;
});

What if you wanted to be able to choose which direction it was sorted based on another variable. You can define both sort functions, and then pass the correct one for the sort you want.

var numbers = [4, 2, 5, 1, 3];
var sortAscending = function(a, b) {
return a - b;
}

var sortDescending = function(a, b) {
return b - a;
}

function doSort(myArray, dir) {
var sortMethod = (dir == "asc") ? sortAscending : sortDescending;
myArray.sort(sortMethod );
}

doSort(numbers, "asc");

The above illustrates how passing the method call this way allows for more flexibility when you need it, and ensures the call is made only when it's executed inside sort.

Why variables have to be final in anonymous methods and class fields don't

The local variable is allocated in the stack, and it will fall out of scope after testMethod(). Making the variable final ensures that it is ok to just pass a reference to it to the anonymous class. If it was not final, a later assignment to it in testMethod() could change the value later with confusing results. (The user might expect the later assigned value used, but that would be impossible).

A field of the parent class, however can be accessed through the parent reference of the anonymous class, so any later assignments can be handled without confusion.

Why am I getting NullReferenceException when anonymous method uses a variable declared elsewhere?

It seems to be symptomatic of anonymous method variable scoping in C#. Have you verified in another context that anonymous methods retain access to externally declared variables? Have you tried making it static? This might help you down the path to truth (not necessarily great working code though). public static string imagesDirectory = string.Empty;

The compiler understands that the variable is in scope at compile time, but at runtime the execution of the method is anonymous in the context of the class instance. The instance variable is not available, so it's reference is null.

In C#, why can't I populate a local variable using its address, then use the variable later?

The C# specification says the following (my bold):

23.4 Fixed and moveable variables

The address-of operator (§23.6.5) and the fixed statement (§23.7) divide variables into two categories:

Fixed variables and moveable variables.

...snip...

The & operator (§23.6.5) permits the address of a fixed variable to be obtained without restrictions. However, because a moveable variable is subject to relocation or disposal by the garbage collector, the address of a moveable variable can only be obtained using a fixed statement (§23.7), and that address remains valid only for the duration of that fixed statement.

In precise terms, a fixed variable is one of the following:

  • A variable resulting from a simple-name (§12.7.3) that refers to a local variable, value parameter, or parameter array, unless the variable is captured by an anonymous function (§12.16.6.2).
  • .....

So it's explicitly forbidden by the spec. As to why it's forbidden, for that you would have to ask the language designers, but considering how much complexity is involved in capturing variables, it is somewhat logical.

Why can't an anonymous class have a lambda property, but it can have a Func property?

Because there is no way for the compiler to know the type of () => { return 5; }; it could be a Func<int>, but it could also be any other delegate with the same signature (it could also be an expression tree). That's why you have to specify the type explicitly.

can't call anonymously function again in javascript?


var func = (function(){
//do something
})();

This code has () at the end, i.e. it's already calling the function. The value assigned to func is the return value of the function.

If you want to assign the function itself to func, just do:

var func = function () {
//do something
};


Related Topics



Leave a reply



Submit