Reputation: 473
I'd like to accomplish something like the following:
(clientSinceChoices = Enumerable.Range(1949, DateTime.Now.Year - 1950)
.Select(x => new SelectListItem()
{
Text = x != 1949 ? x.ToString() : "Unselected",
Value = x != 1949 ? new DateTime(x, 1, 1).ToString() : null,
Selected = () =>
{
if (x == 1949 && !ClientSinceYearOnly.HasValue)
return true;
else if (ClientSinceYearOnly.Value == x)
return true;
else
return false;
}
}));
I want the value of Selected
to be the result of the labmda expression that is defined inline. I know I can accomplish this by assigning the lambda to a variable and then invoking it, but I think that defining and immediately invoking it is "cleaner".
Upvotes: 3
Views: 6236
Reputation: 659994
First off, to actually answer your question: you can invoke a lambda "in place" by casting it to a delegate:
bool x = ((Func<bool>) ()=>true) ();
But in your code there is no need for the lambda in the first place; I don't see why you have a lambda at all. You want to compute a Boolean, so compute the Boolean:
Selected = (x == 1949 && !ClientSinceYearOnly.HasValue) ||
(ClientSinceYearOnly.Value == x)
(Also, note that you do not have to check to see if the nullable has a value before you compare it; equality is "lifted to nullable" in C#.)
Second, this query is a mess because you've got a special case in there. I would not write your query like this in the first place. I would rather say:
var choices = new List<Item>();
choices.Add(new SelectListItem()
{
Text = "Unselected",
Value = null;
Selected = ClientSinceYearsOnly == null
};
choices.AddRange(
Enumerable.Range(1950, DateTime.Now.Year - 1951)
.Select(x => new SelectListItem()
{
Text = x.ToString(),
Value = new DateTime(x, 1, 1).ToString(),
Selected = x == ClientSinceYearOnly
});
Much clearer. Or, write yourself an extension method that sticks something onto the start of a sequence:
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> sequence, T first)
{
yield return first;
foreach(T item in sequence)
yield return item;
}
and then:
var choices =
Enumerable.Range(1950, DateTime.Now.Year - 1951)
.Select(x => new SelectListItem()
{
Text = x.ToString(),
Value = new DateTime(x, 1, 1).ToString(),
Selected = x == ClientSinceYearOnly
})
.Prepend(new SelectListItem()
{
Text = "Unselected",
Value = null;
Selected = ClientSinceYearsOnly == null
});
Upvotes: 10
Reputation: 86708
This isn't the best use for a lambda, but the way you invoke a lambda inline is just by putting parentheses after it:
(clientSinceChoices = Enumerable.Range(1949, DateTime.Now.Year - 1950)
.Select(x => new SelectListItem()
{
Text = x != 1949 ? x.ToString() : "Unselected",
Value = x != 1949 ? new DateTime(x, 1, 1).ToString() : null,
Selected = ((Func<bool>)(() =>
{
if (x == 1949 && !ClientSinceYearOnly.HasValue)
return true;
else if (ClientSinceYearOnly.Value == x)
return true;
else
return false;
}))() // <-- the () calls the function
}));
Upvotes: 1
Reputation: 54877
The following code is functionally equivalent:
Selected =
x == 1949 && !ClientSinceYearOnly.HasValue ||
ClientSinceYearOnly.Value == x;
Upvotes: 0
Reputation: 46183
You could always put the conditional in a method and invoke that:
public static bool ShouldBeSelected(int x)
{
if (x == 1949 && !ClientSinceYearOnly.HasValue)
return true;
else if (ClientSinceYearOnly.Value == x)
return true;
else
return false;
}
Then you can just use it:
(clientSinceChoices = Enumerable.Range(1949, DateTime.Now.Year - 1950)
.Select(x => new SelectListItem()
{
Text = x != 1949 ? x.ToString() : "Unselected",
Value = x != 1949 ? new DateTime(x, 1, 1).ToString() : null,
Selected = ShouldBeSelected(x)
}));
Also, in your case, you could use a series of logical operators since you're returning a boolean (not recommended if you don't want the future maintainers to kill you in your sleep):
(x == 1949 && !ClientSinceYearOnly.HasValue) || (ClientSinceYearOnly.Value == x)
Upvotes: 5