After reading this article, I can't figure out why lambda expressions are ever used. To be fair, I don't think I have a proper understanding of what delegates and expression tree types are, but I don't understand why anyone would use a lambda expression instead of a declared function. Can someone enlighten me?
First: brevity and locality:
Which would you rather write, read and maintain? This:
var addresses = customers.Select(customer=>customer.Address);
or:
static private Address GetAddress(Customer customer)
{
return customer.Address;
}
... a thousand lines later ...
var addresses = customers.Select(GetAddress);
What's the point of cluttering up your program with hundreds or thousands of four-line functions when you could just put the code you need where you need it as a short expression?
Second: lambdas close over local scopes
Which would you rather read, write and maintain, this:
var currentCity = GetCurrentCity();
var addresses = customers.Where(c=>c.City == currentCity).Select(c=>c.Address);
or:
static private Address GetAddress(Customer customer)
{
return customer.Address;
}
private class CityGetter
{
public string currentCity;
public bool DoesCityMatch(Customer customer)
{
return customer.City == this.currentCity;
}
}
....
var currentCityGetter = new CityGetter();
currentCityGetter.currentCity = GetCurrentCity();
var addresses = customers.Where(currentCityGetter.DoesCityMatch).Select(GetAddress);
All that vexing code is written for you when you use a lambda.
Third: Query comprehensions are rewritten to lambdas for you
When you write:
var addresses = from customer in customers
where customer.City == currentCity
select customer.Address;
it is transformed into the lambda syntax for you. Many people find this syntax pleasant to read, but we need the lambda syntax in order to actually make it work.
Fourth: lambdas are optionally type-inferred
Notice that we don't have to give the type of "customer" in the query comprehension above, or in the lambda versions, but we do have to give the type of the formal parameter when declaring it as a static method. The compiler is smart about inferring the type of a lambda parameter from context. This makes your code less redundant and more clear.
Fifth: Lambdas can become expression trees
Suppose you want to ask a web server "send me the addresses of the customers that live in the current city." Do you want to (1) pull down a million customers from the web site and do the filtering on your client machine, or (2) send the web site an object that tells it "the query contains a filter on the current city and then a selection of the address"? Let the server do the work and send you only the result that match.
Expression trees allow the compiler to turn the lambda into code that can be transformed into another query format at runtime and sent to a server for processing. Little helper methods that run on the client do not.
The primary reason you'd use a lambda over a declared function is when you need to use a piece of local information in the delegate expression. For example
void Method(IEnumerable<Student> students, int age) {
var filtered = students.Where(s => s.Age == age);
...
}
Lambdas allow for the easy capture of local state to be used within the delegate expression. To do this manually requires a lot of work because you need to declare both a function and a containing type to hold the state. For example here's the above without a lambda
void Method(IEnumerable<Student> students, int age) {
var c = new Closure() { Age = age };
var filtered = students.Where(c.WhereDelegate);
...
}
class Closure {
public int age;
bool WhereDelegate(Student s) {
return s.Age == age;
}
}
Typing this out is tedious and error prone. Lambda expressions automate this process.
Let's leave expression trees out of the equation for the moment and pretend that lambdas are just a shorter way to write delegates.
This is still a big win in the realm of statically typed languages like C# because such languages require lots of code to be written in order to achieve relatively simple goals. Do you need to compare sort an array of strings by string length? You need to write a method for that. And you need to write a class to put the method into. And then good practice dictates that this class should be in its own source file. In any but the smallest project, all of this adds up. When we 're talking about small stuff, most people want a less verbose path to the goal and lambdas are about as terse as it can get.
Furthermore, lambdas can easily create closures (capture variables from the current scope and extend their lifetime). This isn't magic (the compiler does it by creating a hidden class and performing some other transformations that you can do yourself), but it's so much more convenient than the manual alternative.
And then there are expression trees: a way for you to write code and have the compiler transform this code into a data structure that can be parsed, modified and even compiled at runtime. This is an extremely powerful feature that opens the door to impressive functionality (which I definitely consider LINQ to be). And you get it "for free".
http://msdn.microsoft.com/en-us/magazine/cc163362.aspx
Great article on what lambdas are, and why you can/should use them.
Essentially, the lambda expression
provides a shorthand for the compiler
to emit methods and assign them to
delegates; this is all done for you.
The benefit you get with a lambda
expression that you don't get from a
delegate/function combination is that
the compiler performs automatic type
inference on the lambda arguments
They are heavily used with LINQ, actually LINQ would be pretty bad without it. You can do stuff like:
Database.Table.Where(t => t.Field ==
"Hello");
They make it easy to pass a simple piece of functionality to another function. For example, I may want to perform an arbitrary, small function on every item in a list (perhaps I want to square it, or take the square root, or so on). Rather than writing a new loop and function for each of these situations, I can write it once, and apply my arbitrary functionality defined later to each item.
Lambda makes code short and sweet. Consider the following two examples:
public class Student
{
public string Name { get; set; }
public float grade { get; set; }
public static void failed(List<Student> studentList, isFaild fail)
{
foreach (Student student in studentList)
{
if(fail(student))
{
Console.WriteLine("Sorry" + " "+student.Name + " "+ "you faild this exam!");
}
}
}
public delegate bool isFaild(Student myStudent);
class Program
{
static void Main(string[] args)
{
List<Student> studentsList = new List<Student>();
studentsList .Add(new Student { ID = 101, Name = "Rita", grade = 99 });
studentsList .Add(new Student { ID = 102, Name = "Mark", grade = 48 });
Student.failed(studentsList, std => std.grade < 60); // with Lamda
}
}
private static bool isFaildMethod(Student myStudent) // without Lambda
{
if (myStudent.grade < 60)
{
return true;
}
else
{
return false;
}
}
Related
I tried my best to explain in the title, however I am trying to achieve giving linq statements an 'alias' and still use them in dot notation. Allow me to explain further.
below we have a list that has a linq statement applied:
private List<string> _matches;
var output = _matches.Where(x => x.EntityScore == 100).ToList();
I agree that this is simple to read. However I wish to simplify it further especially when the statements start to get bigger. This is an example of linq getting longer than I care for:
private List<string> _matches;
var matchAddressList = _matches.Where(x => x.EntityDetails.Addresses.Any(x => x.Street.Equals(inputObject.Address)
&& x.StateProvinceDistrict.Equals(inputObject.State)
&& x.City.Equals(inputObject.City))).ToList();
What I am trying to do is alias certain groups of LINQ and then call that linq as a dot operator
for example:
var finalOutput = _matches.perfectMatches().addressMatches(inputObject).someOtherMatchCondition(inputObject)
I think the above line is clear and easily readable. Future devs dont necessarily have to look into the logic. They can read the business domain name and understand what it does.
I want to avoid the following line, as I believe the previous code is more clean:
var finalOutput = someOtherMatchCondition(addressMatches(perfectMatches(_matches)));
the previous line is how I feel you would go about it using functions at a basic level. However I am struggling to find a way to create an alias or encapsulate the linq logic into a business domain name and then use that as a dot operator.
I have tried expression body definitions:
public List<string> perfectMatches => _matches.Where(x => x.EntityScore == 100).ToList();
is this going to require extensions of another class? or the writing of generics? or am I perhaps unaware of a standard way of doing this?
Update: maybe this is helpfull too:
How to add custom methods for LINQ queries (C#)
It has to be an extension method to make use of the dot notation.
Do you mean something like that. It is rather pseudo code than working. You may have to play around with the types or try out some kind of generic approach:
public class ProductionCode
{
public void MyMain()
{
var myList = new List<EntityThingType>() { .... };
var newList = myList.PerfectMatches().AddressMatches(myInputObject).ToList();
}
}
public static class test
{
public static IEnumerable<EntityThingType> PerfectMatches(this IEnumerable<EntityThingType> myList)
{
return myList.Where(x => x.EntityScore == 100);
}
public static IEnumerable<EntityThingType> AddressMatches(this IEnumerable<EntityThingType> myList, MyObjectType inputObject)
{
return myList.Where(x => x.EntityDetails.Addresses.Any(x => x.Street.Equals(inputObject.Address)
&& x.StateProvinceDistrict.Equals(inputObject.State)
&& x.City.Equals(inputObject.City)));
}
}
I think what you are looking for is Extension Methods. You can have the perfectMatches() method be an extension method that takes an IEnumerable<string> and return the same. Then you can chain those together.
The code below won't compile:
Func<Person, bool> theLambda = (p) => p.Year >= 1992;
foreach (Person pers in PersonList.FindAll(theLambda))
{
Console.WriteLine(pers.Name);
}
public class Person
{
public string Name { get; set; }
public int Year { get; set; }
public Person(string Name, int Year )
{
this.Name = Name; this.Year = Year;
}
}
However, if I replace variable "theLambda" directly with the lambda, then it works just fine. What's going on here? (Be gentle, I'm a novice). Thank you so much in advance!
(1) I read the error message, but it doesn't mean anything to me.
(2) Yes, I can make it work with a Predicate by using the compile() keyword, but that's not the issue here.
Edit: why would anyone downvote this? The question wasn't that bad at all as the problem domain is not of a logic nature indeed. Really people.
It works because if you declare the lambda inline the compiler implicitly assigns it the right type, i.e. Predicate<Person>. You don't have to explicitly tell the compiler the lambda type as it knows already that it should take a Person and return a bool if you call FindAll on a List<Person>.
foreach (Person pers in PersonList.FindAll(p => p.Year >= 1992))
{
Console.WriteLine(pers.Name);
}
You can also use Enumerable.Where - LINQ method with the same functionality to make it a bit more readable:
foreach (Person pers in PersonList.Where(p => p.Year >= 1992))
{
Console.WriteLine(pers.Name);
}
From msdn:
When writing lambdas, you often do not have to specify a type for the
input parameters because the compiler can infer the type based on the
lambda body, the parameter’s delegate type, and other factors as
described in the C# Language Specification. For most of the standard
query operators, the first input is the type of the elements in the
source sequence. So if you are querying an IEnumerable<Customer>, then
the input variable is inferred to be a Customer object
The confusing part is that a Predicate is logically a Func that takes an object of some type T and returns a bool, but for some reason this typing doesn't work and you have to use Predicate<T>. Declaring the lambda function inline avoids this confusion as you just write the lambda body and let the compiler infer the type on its own.
The FindAll expects a Predicate and not a Function as seen in the method definition Array.FindAll<T> Method (T[], Predicate<T>)
When you try to pass theLambda it is trying to pass a Function, when the method expects a Predicate. You can instead try defining theLambda as
Predicate<Person> theLambda = (p) => p.Year >= 1992;
A Predicate is a Function that returns a Boolean and that is what is required by the FindAll method to filter the results.
Based on the answer here, you can do the following.
foreach (Person pers in PersonList.FindAll(new Predicate<Person>(theLambda)))
I am using linq2db and while it works well enough for most CRUD operations I have encountered many expressions that it just cannot translate into SQL.
It has gotten to the point where unless I know in advance exactly what kinds of expressions will be involved and have successfully invoked them before, I am worried that any benefit derived from linq2db will be outweighed by the cost of trying to find and then remove (or move away from the server side) the offending expressions.
If I knew how to tell linq2db how to parse an Expression<Func<T,out T>> or whatnot into SQL whenever on an ad-hoc, as-it-is-needed basis, then I would be much more confident and I could do many things using this tool.
Take, for instance, String.Split(char separator), the method that takes a string and a char to return a string[] of each substring between the separator.
Suppose my table Equipment has a nullable varchar field Usages that contains lists of different equipment usages separated by commas.
I need to implement IList<string> GetUsages(string tenantCode, string needle = null) that will give provide a list of usages for a given tenant code and optional search string.
My query would then be something like:
var listOfListOfStringUsages =
from et in MyConnection.GetTable<EquipmentTenant>()
join e in MyConnection.GetTable<Equipment>() on et.EquipmentId = e.EquipmentId
where (et.TenantCode == tenantCode)
where (e.Usages != null)
select e.Usages.Split(','); // cannot convert to sql here
var flattenedListOfStringUsages =
listOfListOfStringUsages.SelectMany(strsToAdd => strsToAdd)
.Select(str => str.Trim())
.Distinct();
var list = flattenedListOfStringUsages.ToList();
However, it would actually bomb out at runtime on the line indicated by comment.
I totally get that linq2db's creators cannot possibly be expected to ship with every combination of string method and major database package.
At the same time I feel as though could totally tell it how to handle this if I could just see an example of doing just that (someone implementing a custom expression).
So my question is: how do I instruct linq2db on how to parse an Expression that it cannot parse out of the box?
A few years ago I wrote something like this:
public class StoredFunctionAccessorAttribute : LinqToDB.Sql.FunctionAttribute
{
public StoredFunctionAccessorAttribute()
{
base.ServerSideOnly = true;
}
// don't call these properties, they are made private because user of the attribute must not change them
// call base.* if you ever need to access them
private new bool ServerSideOnly { get; set; }
private new int[] ArgIndices { get; set; }
private new string Name { get; set; }
private new bool PreferServerSide { get; set; }
public override ISqlExpression GetExpression(System.Reflection.MemberInfo member, params ISqlExpression[] args)
{
if (args == null)
throw new ArgumentNullException("args");
if (args.Length == 0)
{
throw new ArgumentException(
"The args array must have at least one member (that is a stored function name).");
}
if (!(args[0] is SqlValue))
throw new ArgumentException("First element of the 'args' argument must be of SqlValue type.");
return new SqlFunction(
member.GetMemberType(),
((SqlValue)args[0]).Value.ToString(),
args.Skip(1).ToArray());
}
}
public static class Sql
{
private const string _serverSideOnlyErrorMsg = "The 'StoredFunction' is server side only function.";
[StoredFunctionAccessor]
public static TResult StoredFunction<TResult>(string functionName)
{
throw new InvalidOperationException(_serverSideOnlyErrorMsg);
}
[StoredFunctionAccessor]
public static TResult StoredFunction<TParameter, TResult>(string functionName, TParameter parameter)
{
throw new InvalidOperationException(_serverSideOnlyErrorMsg);
}
}
...
[Test]
public void Test()
{
using (var db = new TestDb())
{
var q = db.Customers.Select(c => Sql.StoredFunction<string, int>("Len", c.Name));
var l = q.ToList();
}
}
(and of course you can write your wrappers around Sql.StoredFunction() methods to get rid of specifying function name as a string every time)
Generated sql (for the test in the code above):
SELECT
Len([t1].[Name]) as [c1]
FROM
[dbo].[Customer] [t1]
PS. We use linq2db extensively in our projects and completely satisfied with it. But yes, there is a learning curve (as with almost everything serious we learn) and one needs to spend some time learning and playing with the library in order to feel comfortable with it and see all the benefits it can give.
Try listOfListOfStringUsages.AsEnumerable(). It will enforce executing SelectMany on client side.
UPDATE:
I used the following code to reproduce the issue:
var q =
from t in db.Table
where t.StringField != null
select t.StringField.Split(' ');
var q1 = q
//.AsEnumerable()
.SelectMany(s => s)
.Select(s => s.Trim())
.Distinct()
.ToList();
It's not working. But if I uncomment .AsEnumerable(), it works just fine.
Let say I have this kind of class in c# language:
public class ABC {
public int var_1;
public int var_2;
public int var_3;
//... until 100
public int var_100;
public int GetData_WithBasicIfElse (int id) {
if(id == 1)
return var_1;
else if(id == 2)
return var_2;
else //and so on until
else if(id == 100)
return var_100;
}
public int GetData_WithReflection(int id){
string key = "var_" + id.ToString ();
FieldInfo info = GetType ().GetField (key);
return info != null ? (int)info.GetValue (this) : 0;
}
public int GetData_WithSpecialCode(int id){
//put the simple codes here, then compilers compile it, it will generate code like the method GetData_WithBasicIfElse
}
}
Actually in most cases, I can use the array to hold var_n variable, but I am just curious if there is another way. I do not want to use GetData_WithBasicIfElse (not elegant), but I am wondering if there is another solution beside using reflection.
What I mean with GetData_WithSpecialCode is, it contains the special code that will be transformed by compiler (when compile time, where it will be binary file) into some pattern like GetData_WithBasicIfElse.
UPDATED
This technique's called Template metaprogramming, as you can see in here: http://en.wikipedia.org/wiki/Template_metaprogramming, in the factorial source code.
T4 Template
A T4 Template can generate that desired C# code, that will be later compiled into IL code, as if you have written that code yourself. If you want to use this technique, the most natural way is to use partial classes. The first partial defines all the class except the auto-generated method. The second partial would be generated by a simple T4 template. (In the compiled code there's no difference between a class defined in a single file or in several partials).
Reflection.Emit
If you really want to generate code at runtime, it's much harder to do, but you can do it using Reflection.Emit This allow to directly emit IL at run time.
Expression Trees
This also allows to generate and compile code at run time. It's easier than the second option. See an introudction here.
Reflection
If you want to use your original Reflection solution you should store the FieldInfos in an static structure (array, list, dictionary or whatever) so that you only have the overhead of reflecting the fields once. This will improve the performace.
What to choose
Unless there is a good reason not to do so, I'd prefer the T4 template. It's the easier to implement, and you leave the compiler the reponsibility to compile and optimize your code. besides you don't have to work with "obscure, unusual" concepts.
In general I wouldn't advice you the second option. Between other things, I think this requires full trust. And, you need a good knowledge of what you're doing. You also miss the compiler optimizations.
Using expression trees is not as hard as using Reflection.Emit, but it's still hard to do.
And reflection always add a little overhead, specially if you don't cache the FieldInfos (or PropertyInfos or whatever). I would leave it for cases where is the only solution. For example checking if a property exists or accessing a private or protected member of a class from ouside.
I really wonder why you can't use array. For sure using some kind of dictionary would be better. But believing you really can't, you have at least two options to generate such a method:
1) CSharpCodeProvider
You can build a string with helper class containing your method, and it will be compiled to a different assembly:
string source = "public class Description" +
"{" +
" public int GetData_WithBasicIfElse(int id) {" +
// ... all ifs generated here
" }" +
"}";
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
CompilerResults result = codeProvider.CompileAssemblyFromSource(parameters, source);
if (!result.Errors.HasErrors)
{
Type type = result.CompiledAssembly.GetType("Description");
var instance = Activator.CreateInstance(type);
}
and now you have an instance of helper class
2) Linq Expressions
You can build a method using Linq Expressions
ParameterExpression id = Expression.Parameter(typeof(int), "id");
List<Expression> expressions = new List<Expression>();
// here a lot of adding if-else statement expressions
expressions.Add(...);
var lambda = Expression.Lambda(
Expression.Block(
expressions
),
id);
Then you can use a result of lambda.Compile() as a method to call dynamically.
You can use a dictionary to map the ids:
public class ABC
{
public int var_1;
public int var_2;
public int var_3;
//... until 100
public int var_100;
private Dictionary<int,int> map;
public ABC()
{
//build up the mapping
map = new Dictionary<int,int>();
map.Add(1,var_1);
map.Add(2,var_2);
map.Add(100,var_100);
}
public int GetData(int id)
{
//maybe here you need to do check if the key is present
return map[id];
}
}
Can you change some details in your code? If you define the integers as one Array with 100 elements you can simply use id as an index and return that:
public int GetData_WithSpecialCode(int id){
return var_array(id)
}
If you really need to access the values from outside (they are defined public?) you can expose them using a property wich is preferred to public integers.
I haven't used them, but I know Visual Studio comes with T4 Text Templates that may do what you need.
Of course,
switch (id)
{
case 1:
return this.var_1;
case 2:
return this.var_2;
// etc. etc.
}
or,
var lookup = new Dictionary<int, Func<int>>
{
{ 1, () => return this.var_1 },
{ 2, () => return this.var_2 },
// etc. etc.
};
return lookup[i]();
I'm trying to implement encrypted columns in EF4 and using the CTP5 features to allow simple use of POCO's to query the database. Sorry that this is a lot of words, but I hope the below gives enough to explain the need and the problem!
So, bit of background, and my progress so far:
The intention is that if you query the tables without using our DAL then the data is rubbish, but I don't want the developers to worry about if/when/how the data is encrypted.
For simplicity, at this stage I'm working on the assumption any string column will be encrypted.
Now, I have successfully implemented this for returning the data using the Objectmaterialized event, and for data commits using the SavingChanges event.
So given the following class:
public class Thing
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
public DateTime Date { get; set; }
public string OtherString { get; set; }
}
The below query returns all the required values and the POCO materialized has clear data in it.
var things = from t in myDbContext.Things
select t;
where myDbContext.Things is a DbSet<Thing>
Likewise, passing an instance of Thing to Things.Add()
(with clear string data in the Name and/or OtherString values)
and then calling myDbContext.SaveChanges() encrypts the strings before it gets to the data store.
Now, the problem I have is in this query:
var things = from t in myDbContext.Things
where t.Name == "Hairbrush"
select t;
This results in the unencrypted value being compared to the encrypted value in the DB. Obviously I don't want to get all the records from the database, materialize them, and then filter the results based on any supplied Where clause... so what I need to do is: intercept that query and rewrite it by encrypting any strings in the Where clause.
So I've looked at:
writing a query provider, but that doesn't seem like the right solution... (is it?)
writing my own IQueryable wrapper for the DbSet which will capture the expression, run over it using an expression tree visitor and then forward the new expression to the DbSet...
Attempts at both have left me somewhat lost! I prefer the second solution i think since it feels a bit neater, and is probably clearer to other developers in future. But I'm happy to go with either or another better option!!
The main thing I am struggling with is when/how the LINQ expression is applied to the object... I think i've got myself a bit confused as to where the expression executes in the IQueryable object thus I'm not sure which method I need to implement in my wrapper to then grab and manipulate the expression being passed in...
I'm sure I'm missing something fairly obvious here and I'm waiting for that light bulb moment... but its not coming!!
Any help will be very gratefully received!
Thought I'd let you know what my final solution was.
In the end I have gone a wrapper class which implements a Where method, but without going to the extent of implementing IQueryable entirely. LINQ will still execute against the class (at least to the extent that I want/need it to) and will call the Where method with the expression from the LINQ.
I then traverse this ExpressionTree and replace my strings with encrypted values before forwarding the new expressiontree to the internal DbSet. and then returning the result.
Its pretty crude, and has its limitation, but works for our particular circumstance without problem.
Thanks,
Ben
you should use the QueryInterceptor attribute, search here in SO or in google and you find examples on how to use it.
a snippet:
[QueryInterceptor("Orders")]
public Expression<Func<Order, bool>> FilterOrders()
{
return o => o.Customer.Name == /* Current principal name. */;
}
// Insures that the user accessing the customer(s) has the appropriate
// rights as defined in the QueryRules object to access the customer
// resource(s).
[QueryInterceptor ("Customers")]
public Expression<Func<Customer, bool>> FilterCustomers()
{
return c => c.Name == /* Current principal name. */ &&
this.CurrentDataSource.QueryRules.Contains(
rule => rule.Name == c.Name &&
rule.CustomerAllowedToQuery == true
);
}
You can use David Fowler's Query Interceptor:
https://github.com/davidfowl/QueryInterceptor
One example of its use:
IQueryable q = ...;
IQueryable modifed = q.InterceptWith(new MyInterceptor());
And on class MyInterceptor:
protected override Expression VisitBinary(BinaryExpression node) {
if (node.NodeType == ExpressionType.Equal) {
// Change == to !=
return Expression.NotEqual(node.Left, node.Right);
}
return base.VisitBinary(node);
}