将变量赋值给lambda表达式的结果

时间:2012-03-17 14:19:57

标签: c# lambda

我想完成以下内容:

(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;
        }
    }));

我希望Selected的值是内联定义的labmda表达式的结果。我知道我可以通过将lambda分配给变量然后调用它来实现这一点,但我认为定义并立即调用它是“更干净”。

4 个答案:

答案 0 :(得分:7)

首先,要实际回答你的问题:你可以通过将lambda强制转换为委托来调用lambda“

bool x = ((Func<bool>) ()=>true) ();

但是在你的代码中,首先不需要lambda;我不明白为什么你有一个lambda。您想计算布尔值,因此计算布尔值

Selected = (x == 1949 && !ClientSinceYearOnly.HasValue) || 
                         (ClientSinceYearOnly.Value == x)

(另请注意,在比较之前,您无需检查可空值是否具有值;在C#中,相等性已“提升为可空”。)

其次,这个查询很乱,因为你有一个特殊情况。我不会在第一时间写这样的查询。我宁愿说:

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
    });

更清楚。或者,给自己写一个扩展方法,将某些内容粘贴到序列的开头:

public static IEnumerable<T> Prepend<T>(this IEnumerable<T> sequence, T first)
{
    yield return first;
    foreach(T item in sequence) 
        yield return item;
}

然后:

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
    });

答案 1 :(得分:4)

您总是可以将条件放在方法中并调用:

public static bool ShouldBeSelected(int x)
{
    if (x == 1949 && !ClientSinceYearOnly.HasValue)
        return true;
    else if (ClientSinceYearOnly.Value == x)
        return true;
    else
        return false;
}

然后你可以使用它:

        (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)
                                        }));

另外,在你的情况下,你可以使用一系列逻辑运算符,因为你返回一个布尔值(不推荐如果你不希望未来的维护者在你的睡眠中杀死你) :

(x == 1949 && !ClientSinceYearOnly.HasValue) || (ClientSinceYearOnly.Value == x)

答案 2 :(得分:1)

这不是lambda的最佳用法,但是你调用lambda内联的方式就是在它后面添加括号:

(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
    }));

答案 3 :(得分:0)

以下代码在功能上是等效的:

Selected = 
    x == 1949 && !ClientSinceYearOnly.HasValue ||
    ClientSinceYearOnly.Value == x;