I have this line of code, it works but I don't understand it:
Genres.Find(delegate (Genre genre) { return genre.Id == id; });
Genres is a list of genre(music)
What exactly is happening here?
C# provides two ways of defining delegates without writing a named method for it - the old anonymous method syntax introduced in C# 2.0, and the shorter lambda syntax introduced in C# 3.0.
Your code is the old way of writing this:
Genres.Find(genre => genre.Id == id);
This article describes the evolution of anonymous functions in C#.
Your Find method takes a predicate delegate. Depending on the version of .NET targeted by your code it may or may not be the System.Predicate<T> delegate, but its functionality is equivalent. An anonymous method in parentheses provides an implementation of your predicate, allowing you to pass arbitrary conditions to your Find(...) method.
It says, find the Genre (from the list Genres) which has the Id equal to the value from the variable id.
The keyword delegate says, that this is a kind of inline function which decides whether the check is true for each item or not. The beginning (Genre genre) says "given I would call each element genre in the loop, I can check each items' Id with its named variable Id". This is: genre.Id == id.
A modern approach would be the usage of lambdas like:
var x = Genres.Find(g => g.Id == id);
In this case g is your loop variable you can check against.
An intuitive way to see it:
Genres.Find( --- The CompareGenres function is being called from here --- );
bool CompareGenres(Genre genre)
{
return genre.Id == id;
}
Find accepts a Predicate < T >, T is the type of the parameter, in this case: you're passing an instance of Genre which is being supplied by the Find method.
"The Predicate is a delegate to a method that returns true if the object passed to it matches the conditions defined in the delegate."
So you're just passing a method as a parameter in the form of a delegate
Maybe I do not use the right terms here. But form an abstract point of view: The Find method here accepts a delegate as parameter. It allows you to implement the "find" algorithm (here comparing the id). It is flexible code you could also compare any other object of "genre".
Related
I import data from a csv file and then store it in a list (List<Customer> customers). The data is added to the list by creating and adding objects. The objects are created using constructors which take the contents of the file as parameters, everything is string. The list is of type Customer from what I understand. I want to make an if statement to check whether user input (string) exists in the list.
I tried this code:
ImportData("CustomerData.csv");
Console.WriteLine("Please provide customer name:");
string customer_Name = Console.ReadLine();
//if (customers.Contains(customer_Name))
bool b = customers.Contains(customer_Name);
//if (customers.Any(customers.Contains(customer_Name)))
if (b)
Nothing works, I get the error CS1503 Argument 1: cannot convert from 'string' to 'MyNameSpace.Customer'. I don't really understand what it means. I think maybe it is because of the list being of <Customer> type? I also have a class called Customer. I tried to change the list type to <string>, it didn't help.
List.Contains requires you to supply a customer object. As you've likely NOT overridden Equals and GetHashcode to allow two different instances of customer to be considered equal, it's probably pointless to use, as it would need you to find an instance of a customer you wanted in the list, then ask the list if it Contains the instance you found (which you already know)
IEnumerable.Any requires you to supply a method or small function (often called a lambda) that operates on a customer object and returns true or false. This is more useful to your situation
The short form looks like:
if (customers.Any(c => c.CustomerName == customer_Name))
The c => c.CustomerName == customer_Name is a mini method (lambda):
c the argument to the method; implicitly a Customer (hence why I named it c) for reasons I'll go into in a moment
=> the separator between arguments and body; C# uses it to understand that youre making a lambda
c.CustomerName == customer_Name a statement that resolves to a boolean
In long form it might look like:
bool SomeMethod(Customer c){
return c.CustomerName == customer_Name;
}
We can shorten this long form to the short form because the compiler can figure out a lot of the stuff:
It's a rule that Any needs something that returns a boolean, so we don't need the bool.
It's implied that the input argument c is a Customer because the List is full of Customers.
We can ditch the { return ... } because C# has expression bodies; "arguments on the left, then a =>, then a single statement that resolves to the return value type we first mentioned" means we're allowed to skip using curly brackets and the return keyword
When writing a lamdba we don't need to give it a name, because we never refer to it by name anywhere; it is purely embodied by its definition and only used by the one thing we give it to, so it can remain nameless
So our long form gradually boils down:
//long form: a class level method
bool SomeMethod(Customer c){
return c.CustomerName == customer_Name;
}
//shorter: expression body; this is still valid C# to put in a class and you could write all your "one line return" methods like this
bool SomeMethod(Customer c) => c.CustomerName == customer_Name;
//shortest: a lambda, this has to be stored in a variable or used in a method call that accepts a lambda - you cannot write this in a class level statemetn because the compiler needs some surrounding context to figure bits of it out
c => c.CustomerName == customer_Name
If you take a look at the docs for Any it tells you waht you have to supply:
Here's how to decipher this:
Any is a method that can be called on an IEnumerable. List is IEnumerable, so Any can be called on a List. A List is full of objects that have a particular type, TSource. TSource would be replaced by whatever is in the list, in this case a Customer for you. The word this means it's an extension method; a trick that means it looks like you can call it directly on a List of customers:
//you could do this; call Any and pass customers in
Enumerable.Any(customers, ...)
//but its more normal, readable etc to do this:
customers.Any(...)
The use of this on the first argument allows you to write like the latter, and the compiler will understand it to be the former. It lets you "make it look like you added a method to the thing youre calling it on, even though you didn't"
The more interesting part is the Func<TSource,bool> argument. This means "A function that takes a TSource and returns a bool". Remember, TSource for your List<Customer> means "a Customer".
The last thing mentioned is the return type, everything else is an argument to a method. If you saw Funct<string, int, TSource, DateTime> it would mean "A function or method that has 3 input arguments; a string, int and TSource (Customer) in taht order, and must return a DateTime". Any method that matches this signatore is allowed to be supplied.
Circling back to Funct<TSource, bool> for Any; you have to supply a method that takes a TSource (Customer, in your case) and returns a bool.
This matches that:
private string customer_Name = "john" //class level variable
//method that matches the rule "takes a Customer, returns a bool"
bool SomeMethod(Customer c){
return c.CustomerName == customer_Name;
}
//can be passed to list's Any
customers.Any(SomeMethod)
This shorter form also matches that:
customers.Any(c => c.CustomerName == customer_Name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
also a method that "takes a customer, returns a bool"
Any will take the method you give it and start looping the list, calling the method and passing in the current customer it is looping. As soon as it gets a true it stops and returns true, because it has discovered that "Any customer matches ..." is true
I get the error CS1503 Argument 1: cannot convert from 'string' to 'MyNameSpace.Customer'. I don't really understand what it means
Hopefully now you can see, if you do:
customers.Any("John")
customers.Any needs you to provide "a method that takes a Customer and returns a bool" a.k.a Func<Customer,bool> - you cannot provide a string like "John" because a string is not a Func<Customer,bool>..
..and think about it. If you did provide a string like "John" - how does C# know that's the name you want to look up, and not the address?
Providing a method as an argument rather than providing data as an argument is perhaps the biggest thing to get your head round here; why do Microsoft write code that accepts methods instead of data? Because simply put, they cannot possibly code for all the variations of how people will use List, so instead they just say "We'll loop the list, calling some bit of code we cannot imagine - the bit that you supply - and if your code returns true, we'll return true"
It's natural that Microsoft write C# but there are bits missing that only you can know - hence why "passing methods around like data" is vital
customers is a List<T> where T is Customer, your error is telling you that it can't convert a string to the class type Customer, what I think you want is to use Linq to look for any Customer objects who's property of xxx (Customer Name) equals the user input, you could do this, where you'd replace somestringproperty with your classes property name:
bool b = customers.Any(a => a.somestringproperty == customer_Name);
In a project I'm currently working on, we have many static Expressions that we have to bring in local scope with a variable when we call the Invoke method on them and pass our lambda expressions' arguments to.
Today, we declared a static method whose parameter is exactly the type that the query is expecting. So, my coworker and I were messing around to see if we could get this method to do the project in the Select statement of our query, instead of invoking it on the whole object, without bringing it into local scope.
And it worked! But we do not understand why.
Imagine code like this
// old way
public static class ManyExpressions {
public static Expression<Func<SomeDataType, bool> UsefulExpression {
get {
// TODO implement more believable lies and logic here
return (sdt) => sdt.someCondition == true && false || true;
}
}
}
public class ARealController : BaseController {
/* many declarations of important things */
public ARealClass( /* many ninjected in things */) {
/* many assignments */
}
public JsonNet<ImportantDataResult> getSomeInfo(/* many useful parameter */) {
var usefulExpression = ManyExpressions.UsefulExpression;
// the db context is all taken care of in BaseController
var result = db.SomeDataType
.Where(sdt => usefulExpression.Invoke(sdt))
.Select(sdt => new { /* grab important things*/ })
.ToList();
return JsonNet(result);
}
}
And then you get to do this!
// new way
public class SomeModelClass {
/* many properties, no constructor, and very few useful methods */
// TODO come up with better fake names
public static SomeModelClass FromDbEntity(DbEntity dbEntity) {
return new SomeModelClass { /* init all properties here*/ };
}
}
public class ARealController : BaseController {
/* many declarations of important things */
public ARealClass( /* many ninjected in things */) {
/* many assignments */
}
public JsonNet<SomeModelClass> getSomeInfo(/* many useful parameter */) {
// the db context is all taken care of in BaseController
var result = db.SomeDataType
.Select(SomeModelClass.FromDbEntity) // TODO; explain this magic
.ToList();
return JsonNet(result);
}
}
So when ReSharper prompts me to do this (which is not often, as this condition of matching the type that is expected by the Delegate isn't often satisfied), it says convert to a Method Group. I kind of vaguely understand that a Method Group is a set of methods, and the C# compiler can take care of converting the method group to an explicitly typed and appropriate overload for the LINQ provider and what not... but I'm fuzzy on why this works exactly.
What's going on here?
It's great to ask a question when you don't understand something, but the problem is that it can be hard to know which bit someone doesn't understand. I hope I help here, rather than tell you a bunch of stuff you know, and not actually answer your question.
Let's go back to the days before Linq, before expressions, before lambda, and before even anonymous delegates.
In .NET 1.0 we didn't have any of those. We didn't even have generics. We did though have delegates. And a delegate is related to a function pointer (if you know C, C++ or languages with such) or function as argument/variable (if you know Javascript or languages with such).
We could define a delegate:
public delegate int MyDelegate(double someValue, double someOtherValue);
And then use it as a type for a field, property, variable, method argument or as the basis of an event.
But at the time the only way to actually give a value for a delegate was to refer to an actual method.
public int CompareDoubles(double x, double y)
{
if (x < y) return -1;
return y < x ? 1 : 0;
}
MyDelegate dele = CompareDoubles;
We can invoke that with dele.Invoke(1.0, 2.0) or the shorthand dele(1.0, 2.0).
Now, because we have overloading in .NET, we can have more than one thing that CompareDoubles refers to. That isn't a problem, because if we also had e.g. public int CompareDoubles(double x, double y, double z){…} the compiler could know that you could only possibly have meant to assign the other CompareDoubles to dele so it's unambiguous. Still, while in the context CompareDoubles means a method that takes two double arguments and returns an int, outside of that context CompareDoubles means the group of all the methods with that name.
Hence, Method Group which is what we call that.
Now, with .NET 2.0 we got generics, which is useful with delegates, and at the same time in C#2 we got anonymous methods, which is also useful. As of 2.0 we could now do:
MyDelegate dele = delegate (double x, double y)
{
if (x < y) return -1;
return y < x ? 1 : 0;
};
This part was just syntactic sugar from C#2, and behind the scenes there's still a method there, though it has an "unspeakable name" (a name that is valid as a .NET name but not valid as a C# name, so C# names can't clash with it). It was handy if, as was often the case, one was creating methods just to have them used once with a particular delegate though.
Move forward a bit further, and at .NET 3.5 have covariance and contravariance (great with delegates) the Func and Action delegates (great for reusing the same name based on type, rather than having a bunch of different delegates which were often very similar) and along with it came C#3 which had lambda expressions.
Now, these are a bit like anonymous methods in one use, but not in another.
That's why we can't do:
var func = (int i) => i * 2;
var works out what it means from what's been assigned to it, but lamdas work out what they are from what they've been assigned to, so this is ambiguous.
It could mean:
Func<int, int> func = i => i * 2;
In which case it's shorthand for:
Func<int, int> func = delegate(int i){return i * 2;};
Which in turn is shorthand something like for:
int <>SomeNameImpossibleInC# (int i)
{
return i * 2;
}
Func<int, int> func = <>SomeNameImpossibleInC#;
But it can also be used as:
Expression<Func<int, int>> func = i => i * 2;
Which is shorthand for:
Expression<Func<int, int>> func = Expression.Lambda<Func<int, int>>(
Expression.Multiply(
param,
Expression.Constant(2)
),
param
);
And we also with .NET 3.5 have Linq which makes heavy use of both of these. Indeed, Expressions is considered part of Linq and is in the System.Linq.Expressions namespace. Note that the object we get here is a description of what we want done (take the parameter, multiply it by two, give us the result) not of how to do it.
Now, Linq operates in two main ways. On IQueryable and IQueryable<T> and on IEnumerable and IEnumerable<T>. The former defines operations to be used on "a provider" with just what "a provider does" being up to that provider, and the latter defines the same operations on in-memory sequences of values.
We can move from one to the other. We can turn an IEnumerable<T> into an IQueryable<T> with AsQueryable which will give us a wrapper on that enumerable, and we can turn the IQueryable<T> into an IEnumerable<T> just by treating it as one, because IQueryable<T> derives from IEnumerable<T>.
The enumerable form uses the delegates. A simplified version of how Select works (there are many optimisations this version leaves out, and I'm skipping error checking and in indirection to ensure that error checking happens immediately) would be:
public static IEnumerable<TResult> Select(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
foreach(TSource item in source) yield return selector(item);
}
The queryable version on the other hand works by taking the expression tree from the Expression<TSource, TResult> making it part of an expression that includes the call to Select, and the source queryable, and returns an object wrapping that expression. So in other words a call to queryable's Select returns an object that represents a call to queryable's Select!
Just what is done with that depends on the provider. Database providers turn them into SQL, enumerables call Compile() on the expression to create a delegate and then we're back at the first version of Select above, and so on.
But that history considered, let's go backwards through the history again. A lambda can represent either an expression or a delegate (and if an expression, we can Compile() it to get the same delegate). A delegate is a way of pointing to a method through a variable, and a method is part of a method group. All of this is built on technology which in the first version could only be called by creating a method and then passing that.
Now, lets say we have a method that takes a single argument and has a result.
public string IntString(int num) { return num.ToString(); }
Now lets say we referenced it in a lambda selector:
Enumerable.Range(0, 10).Select(i => IntString(i));
We have a lambda creating an anonymous method for a delegate, and that anonymous method in turn calls a method with the same argument and return types. In a way that's a bit like if we had:
public string MyAnonymousMethod(int i){return IntString(i);}
MyAnonymousMethod is a bit pointless here; all it does is call IntString(i) and return the result, so why not just call IntString in the first place and cut out going through that method:
Enumerable.Range(0, 10).Select(IntString);
We've cut out a needless (though see note below about delegate caching) level of indirection by taking the lambda-based delegate and converting it to a method group. Hence ReSharper's advice "Convert to Method Group" or however it's worded (I don't use ReSharper myself).
There is though something to be careful of here. IQueryable<T>'s Select only takes expressions, so the provider can try to work out how to convert it to its way of doing stuff (e.g. SQL against a database). IEnumerable<T>'s Select only takes delegates so they can be executed in the .NET application itself. We can go from the former to the latter (when the queryable is really a wrapped enumerable) with Compile(), but we can't go from the latter to the former: We don't have a way of taking a delegate and turning it into an expression that means anything other than "call this delegate" which isn't something that can be turned into SQL.
Now when we use a lambda expression like i => i * 2 it will be an expression when used with IQueryable<T> and a delegate when used with IEnumerable<T> due to overload resolution rules favouring the expression with queryable (as a type it can handle both, but the expression form works with the most derived type). If though we explicitly give it a delegate, whether because we typed it somewhere as Func<> or it comes from a method group, then the overloads taking expressions aren't available and those taking delegates are used. This means it doesn't get passed to the database but rather the linq expression up to that point becomes the "database part" and it gets called and the rest of the work done in memory.
95% of the time that's best avoided. So 95% of the time if you get advice of "convert to method group" with a database-backed query you should think "uh oh! that's actually a delegate. Why is that a delegate? Can I change it to be an expression?". Only the remaining 5% of the time should you think "that'll be slightly shorter if I just pass in the method name". (Also, using a method group instead of a delegate prevents caching of delegates the compiler can do otherwise, so it might be less efficient).
There, I hope I covered the bit that you didn't understand in the course of all that, or at least there's a bit here you can point to and say "that bit there, that's the bit I don't grok".
Select(SomeModelClass.FromDbEntity)
This uses Enumerable.Select which is not what you want. This transitions out of "queryable-LINQ" into LINQ to objects. This means the database cannot execute this code.
.Where(sdt => usefulExpression.Invoke(sdt))
Here, I assume you meant .Where(usefulExpression). This passes the expression into the expression tree underlying the query. The LINQ provider can translate this expression.
When you perform experiments like this use SQL Profiler to see what SQL goes over the wire. Make sure all relevant parts of the query are translatable.
I don't want to disappoint you, but there is no magic at all. And I would suggest you to be very careful with this "new way".
Always check the result of a function by hovering it in VS. Remember that IQueryable<T> "inherits" IEnumerable<T> and also Queryable contains the extension methods with the same names as the Enumerable, and the only difference is that the former works with Expression<Func<...>> while the later just with Func<..>.
So anytime you use Func or method group over IQueryable<T>, the compiler will pick the Enumerable overload, thus silently switching from LINQ to Entities to LINQ to Objects context. But there is a huge difference between the two - this former is executed in database while the later in memory.
The key point is to stay as long as possible in the IQueryable<T> context, so the "old way" should be preferred. E.g. from your examples
.Where(sdt => sdt.someCondition == true && false || true)
or
.Where(ManyExpressions.UsefulExpression)
or
.Where(usefulExpression)
but not
.Where(sdt => usefulExpression.Invoke(sdt))
And never
.Select(SomeModelClass.FromDbEntity)
This solution threw up some red flags for me. Key among them was:
var result = db.SomeDataType
.Select(SomeModelClass.FromDbEntity) // TODO; explain this magic
.ToList(); // <<!!!!!!!!!!!!!
Whenever you're dealing with Entity Framework, you can read "ToList()" as "Copy the whole thing into memory." So "ToList()" should only be done at the last possible second.
Consider: there are lots of useful object you can pass around when dealing with EF:
The database context
The specific dataset you're targeting (e.g. context.Orders)
Queries against a context:
.
var query = context.Where(o => o.Customer.Name == "John")
.Where(o => o.TxNumber > 100000)
.OrderBy(o => o.TxDate);
//I've pulled NO data so far! "var query" is just an object I can pass around
//and even add on to! For example, I can now do this:
query = query.ThenBy(o => o.Items.Description); //and now I've appended that to my query
The real magic is that those lambdas can be thrown in to a variable too. Here's a method I use in one of my projects to do that:
/// <summary>
/// Generates the Lambda "TIn => TIn.memberName [comparison] value"
/// </summary>
static Expression<Func<TIn, bool>> MakeSimplePredicate<TIn>(string memberName, ExpressionType comparison, object value)
{
var parameter = Expression.Parameter(typeof(TIn), "t");
Expression left = Expression.PropertyOrField(parameter, memberName);
return (Expression<Func<TIn, bool>>)Expression.Lambda(Expression.MakeBinary(comparison, left, Expression.Constant(value)), parameter);
}
With this code, you can write something like the following:
public GetQuery(string field, string value)
{
var query = context.Orders;
var condition = MakeSimplePredicate<Order>(field, ExpressionType.Equal, value);
return query.Where(condition);
}
The best thing is that at this time, no data call has been. You can continue to add conditions as you wish. When you're ready to fetch the data, simply iterate through it or call ToList().
Enjoy!
Oh, and check this out if you'd like to see a more thoroughly-developed solution, albeit from a different context.
My Post on Linq Expression Trees
I know what this code is doing but I'm not sure on the syntax. It doesn't seem to conform to a "standard" format. Is it mostly LINQ?
return db.Subjects.SingleOrDefault(s => s.ID == ID);
The first part makes sense but it's the part in the brackets I don't understand. How can we use s without declaring it? And how are we putting logic into a method call?
The first part makes sense but it's the part in the brackets I don't understand.
What are you seeing here is a lambda expression. It's a very special anonymous delegate.
Is it mostly LINQ?
Enumerable.SingleOrDefault is a LINQ method, but the lambdas are something independent of LINQ; they just make LINQ incredibly more friendly then it otherwise would be.
Now, to get specific IEnumerable<Subject>.SingleOrDefault(s => s.ID == ID) returns the unique instance of Subject in the IEnumerable<Subject> that matches the predicate s => s.ID == ID or it returns null if there is no such instance. It throws an exception if there is more than one such instance. At compile-time s => s.ID == ID is translated into a full-blown delegate the eats objects of type Subject and returns a bool that is true if and only if s.ID is equal to ID.
How can we use s without declaring it?
The => is the lambda operator. It basically separates the left-hand side of the lambda expression from the right-hand side. The left-hand side are the input variables. It's equivalent to the parameter list in an explicitly-defined method. That is s in the lambda expression plays the role of s below:
public bool Predicate(Subject s)
It's just that you don't have to declare the type of s as the compiler will infer it.
The right-hand side the lambda body. It's equivalent to the body below
public bool Predicate(Subject s) {
return s.ID == ID;
}
What is more, you don't have to declare the return type; the compiler will infer that to.
So, in the end it is as if you did the following:
class MyPredicate {
public string ID;
public bool Predicate(Subject s) {
return s.ID == this.ID;
}
}
Then:
// elements is IEnumerable<Subject>
// ID is string
MyPredicate predicate = new MyPredicate();
predicate.ID = ID;
elements.SingleOrDefault(predicate.Predicate);
The nice thing is the compiler just automatically spits this out for you when you use a lambda expression.
It is called a Lambda Expression. See here for an explanation.
Lambda Expressions (C# Programming Guide)
It's the C# 3.0 compiler working some magic for you.
That statement gets compiled into a delegate, and is equivalent to:
return db.Subjects.SingleOrDefault(delegate(s) { return s.ID == ID });
It's called a lambda expression since you don't need to formally declare the parameters, they are inferred by the C# compiler.
I think your confusion lies around the expression s => s.ID== ID. This is a lambda expression. It simple terms it's a way of definining an inline function.
In this case the text to the left side of the => is the argument list. So s is declared by virtue of being in it's position. The right side of the => is the expression executed. In this particular context the lambda will be run on every element in the collection and the code will assert there is one value which meets the expression executed by the lambda.
That's a Lambda Expression.
s before => declares a variable with type of structure element (type contained in Subjects variable EDIT: Other functions works with more arguments ie. Join) that goes in the right part ( after => ). Logic comes from function. If you call SingleOrDefault (lookup in docs) it will return SINGLE element if satisfy condition or NULL. There are many functions in LINQ that u can use (ie. First(), Where(), ...). Hope that helps.
(Note the code is an example)
I have the following syntax:
SomeMethod(() => x.Something)
What do the first brackets mean in the expression?
I'm also curious how you can get the property name from argument that is being passed in. Is this posssible?
What do the first brackets mean in the expression?
It's the lambda syntax for a method that takes no parameters. If it took 1 parameter, it'd be:
SomeMethod(x => x.Something);
If it took n + 1 arguments, then it'd be:
SomeMethod((x, y, ...) => x.Something);
I'm also curious how you can get the property name from argument that is being passed in. Is this possible?
If your SomeMethod takes an Expression<Func<T>>, then yes:
void SomeMethod<T>(Expression<Func<T>> e) {
MemberExpression op = (MemberExpression)e.Body;
Console.WriteLine(op.Member.Name);
}
The () is an empty argument list. You're defining an anonymous function that takes no arguments and returns x.Something.
Edit: It differs from x => x.Something in that the latter requires an argument and Something is called on that argument. With the former version x has to exist somewhere outside the function and Something is called on that outside x. With the latter version there does not have to be an outside x and even if there is, Something is still called on the argument to the function and nothing else.
It's a lambda expression. That is, it's a way to create an anonymous function or delegate.
The general form is:
(input parameters) => expression
If you have
() => expression
then you have created a function that takes no arguments, and returns the result of the expression.
C# uses type inference to figure out what the types of the values are, and it captures local variables (like your "x" variable) by means of a lexical closure.
I assume x is declared in somewhere inside your method, if yes, you can compare this lambda expression with a delegate that has no paramaters and return the type of x.someproperty
delegate{
return x.someproperty;
}
that is the same as:
() => x.someproperty
the () mean that this method doesn't take any parameters.
for example, if you assign a normal event handler using a lambda expression, it would look like this:
someButton.Click += (s, e) => DoSomething();
See also the following two blog posts that discuss exactly your second question and provide alternative approaches:
How to Find Out Variable or Parameter Name in C#?
How to Get Parameter Name and Argument Value From C# Lambda via IL? (Or "How NOT to Use .NET Linq Expressions in Order to Get Parameter Name and Argument Value From C# Lambda?")
To get the name of the property you need SomeMethod to have an argument of the type of System.Linq.Expressions.Expression<System.Func<object>>. You can then go through the expression to determine the property name.
I am curious why C# allows me to ignore delegate parameters in some cases but not others.
For instance this is permitted:
Action<int> action = delegate { Console.WriteLine("delegate"); };
but this is not:
Action<int> action = () => Console.WriteLine("lambda");
Is there a way to initialize a delegate and ignore the parameters using a lambda? I know that I can add a single parameter to the lambda and fix the previous line but this is more of an academic question pertaining to the compiler and why or how this works.
I believe that your first sample actually creates an anonymous function that is able to take on many different signatures whose body is the single statement Console.WriteLine.... Because it can match different signatures, it does not cause a problem. In the second sample, the lambda syntax itself defines a function that takes no parameters with the same body. Obviously the latter is not consistent with the defined Action so you get the error.
C# Anonymous Method Reference
There is one case in which an
anonymous method provides
functionality not found in lambda
expressions. Anonymous methods enable
you to omit the parameter list, and
this means that an anonymous method
can be converted to delegates with a
variety of signatures. This is not
possible with lambda expressions.
To elaborate on tvanfosson's answer; this behavior is described in the C# 3.0 language specification (§7.14):
The behavior of lambda-expressions and
anonymous-method-expressions is the
same except for the following points:
• anonymous-method-expressions permit
the parameter list to be omitted
entirely, yielding convertibility to
delegate types of any list of value
parameters.
• lambda-expressions permit parameter
types to be omitted and inferred
whereas anonymous-method-expressions
require parameter types to be
explicitly stated.
• The body of a lambda-expression can
be an expression or a statement block
whereas the body of an
anonymous-method-expression must be a
statement block.
• Since only lambda-expressions can
have an expression body, no
anonymous-method-expression can be
successfully converted to an
expression tree type (§4.6).
I think:
Action<int> action = () => Console.WriteLine("lambda");
is the equivalent of:
Action<int> action = delegate() { Console.WriteLine("delegate"); };
which wouldn't compile either. As Daniel Plaisted says () is explicitly saying there aren't any parameters.
If there were an equivalent of delegate{} it might be:
Action<int> action = => Console.WriteLine("lambda")
Which isn't very pretty and I suspect it suspect isn't in the spirit of lambda expressions.
As others said, no, you can't skip declaring the parameters to a lambda. But, for cleanliness, I suggest giving them a name such as _. For example
foo.Click += (_,__) => { ... }
You aren't ignoring them per-se, but you're indicating you don't care what they are and will not use them.
The () => ... syntax explicitly specifies that the lambda takes no parameters. Perhaps the language could be modified so that () => really meant "Infer the parameters of this lambda for me" in the same way the delegate syntax does, but that would make the language more complicated. When designing new language features, you start at minus 100, and I don't think this one passes the test.
There may also be more technical reasons why this would be difficult to implement (which is probably more in line with what you were asking for, but I doubt the technical reasons drove this decision if it ever came up).
I'd say it's to have a forced use of the parameters of the lambda expression.
Take your first example, how would you interact with the passed in value, there's no local representation of it.
What about this?
Func<int> lamdapointer = () => TwoArgMethodThatReturnsInt(10,20); // the same method cannot be called with the delegate "NoArgmethodThatReturnsInt"
lamdapointer();
Delegate int NoArgmethodThatReturnsInt();
NoArgmethodThatReturnsInt del = NoArgmethodThatReturnsInt; // only this is possible with delegates
public int TwoArgMethodThatReturnsInt(int x,int y)
{
return x + y;
}
public int NoArgmethodThatReturnsInt()
{
return 20;
}
Actually, delegate {} does not specify any parameters and fits any delegate method signature - therefore it is permitted in your first construcion.
The Lambda expression () => ...; specifically states parameterless delegate, which contradicts the signature required by Action - a delegate with single parameter.
You may want to use one of the following options.
If you need the action to have a parameter, you can do it the next way ("_" is a legal character for identifier name).
Action<int> action = _ => Console.WriteLine("lambda");
Or you may want to use parameterless Action as follows:
Action action = () => Console.WriteLine("lambda");