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

本文关键字:表达式 结果 lambda 变量 | 更新日期: 2023-09-27 18:28:18

我想完成以下任务:

(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分配给一个变量然后调用它来实现这一点,但我认为定义并立即调用它是"更干净的"。

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

首先,要真正回答您的问题:您可以通过将lambda强制转换为委托来"就地"调用它:

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

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

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

(另外,请注意,在比较之前,您不必检查nullable是否有值;在C#中,相等是"提升为nullable"的。)

其次,这个查询一团糟,因为其中有一个特殊情况。我一开始就不会这样写你的问题。我宁愿说:

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

您可以始终将条件放在方法中并调用它:

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)

这不是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
    }));

以下代码在功能上等效:

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