Can I declare / use some variable in LINQ?
For example, can I write following LINQ clearer?
var q = from PropertyDescriptor t in TypeDescriptor.GetPr
You need let
:
var q = from PropertyDescriptor t in TypeDescriptor.GetProperties(instance)
let name = t.ComponentType.GetProperty(t.Name)
where (name != null)
select name;
If you wanted to do it in query syntax, you could do it in a more efficient (afaik) and cleaner way:
var q = TypeDescriptor
.GetProperties(instance)
.Select(t => t.ComponentType.GetProperty(t.Name))
.Where(name => name != null);
var q = from PropertyDescriptor t in TypeDescriptor.GetProperties(instance)
let u = t.ComponentType.GetProperty(t.Name)
where (u != null)
select u;
Yes, using the let
keyword:
var q = from PropertyDescriptor t in TypeDescriptor.GetProperties(instance)
let nameProperty = t.ComponentType.GetProperty(t.Name)
where (nameProperty != null)
select nameProperty;
There is an alternative that few people know about ( select a into b
):
var q = from PropertyDescriptor t in TypeDescriptor.GetProperties(instance)
select t.ComponentType.GetProperty(t.Name) into u
where u != null
select u;
This translates into:
var q = TypeDescriptor.GetProperties(instance)
.Select(t => t.ComponentType.GetProperty(t.Name))
.Where(prop => prop != null);
Whereas the let
-based version translates to:
var q = TypeDescriptor.GetProperties(instance)
.Select(t => new { t, prop = t.ComponentType.GetProperty(t.Name) })
.Where(x => x.prop != null)
.Select(x => x.prop);
An unnecessary allocation per item because t
is still in scope (yet unused). The C# compiler should just optimize that away, but it doesn't (or the language spec does not allow it, not sure).