如何避免在Short If中复制Lambda表达式?

时间:2016-09-13 15:36:55

标签: c# asp.net asp.net-mvc

有没有办法避免在短时间内写入lambda表达式两次?我经常发现自己处于这种状况,而我所知道的唯一方法就是再次写作!

为了举例,我需要检查一个字符串的长度!

communications.Select(c => new XElement("node",
    new XAttribute("guid", Guid.NewGuid()),
    new XAttribute("title", c.CommunicationDetails.Where(x => x.CultureCode == culture).FirstOrDefault().Title.Length < 40 ? c.CommunicationDetails.Where(x => x.CultureCode == culture).FirstOrDefault().Title : c.CommunicationDetails.Where(x => x.CultureCode == culture).FirstOrDefault().Title.Substring(0, 40)),
    new XAttribute("isHidden", false))))

4 个答案:

答案 0 :(得分:1)

Func<IEnumerable<CommunicationDetails>, string> getFirstDtlTitle = ((dtls) => dtls.Where(x => x.CultureCode == culture).FirstOrDefault()?.Title ?? "");

communications.Select(c => new XElement("node",
                               new XAttribute("guid", Guid.NewGuid()),
                               new XAttribute("title", getFirstDtlTitle(c.CommunicationDetails).Length < 40 ? getFirstDtlTitle(c.CommunicationDetails) : getFirstDtlTitle(c.CommunicationDetails).Substring(0, 40)),
                               new XAttribute("isHidden", false))))

将是重构的第一次尝试。

虽然我也会为字符串修改最大长度做一个扩展方法,所以你只需要调用一个lambda。

所以你最终会得到像这样的东西

Func<IEnumerable<CommunicationDetails>, string> getFirstDtlTitle = ((dtls) => dtls.Where(x => x.CultureCode == culture).FirstOrDefault()?.Title ?? "");

communications.Select(c => new XElement("node",
                               new XAttribute("guid", Guid.NewGuid()),
                               new XAttribute("title", getFirstDtlTitle(c.CommunicationDetails).TrimToLength(40),
                               new XAttribute("isHidden", false))))

答案 1 :(得分:0)

是的,您可以从stringIEnumerable<char>

这一事实中受益
new string(Title.Take(40).ToArray()) //Take will take 40 first elements or as many as there are if less than 40.

或者

string.Concat(Title.Take(40))

由于代码重复,可能性能不高,但更易读,更不容易出错。

正如评论所述,FisrtOrDefault().Title是等待发生的NullReferenceException

答案 2 :(得分:0)

这看起来像缺少字符串API的情况。编写一个允许您传递字符串的方法,最多可以包含40个字符:

static class StringExtensions {
    public static SubstringUpTo(this string str, int len) {
        if (str == null) {
            return null;
        }
        if (len < 0) {
            throw new ArgumentException(nameof(len));
        }
        return len >= str.Length ? str : str.Substring(0, len);
    }
}

这样可以避免第二次获取字符串:

new XAttribute(
    "title"
,   c.CommunicationDetails.FirstOrDefault(x => x.CultureCode == culture)
    ?.Title.SubstringUpTo(40)
)

请注意,如果没有您需要?.的项目,并且CultureCode处理null扩展方法,则使用SubstringUpTo运算符来处理这种情况。

答案 3 :(得分:0)

我认为最好的选择是将标题逻辑提取为单独的方法。这将使事情更有效,更易读,更可测试。

communications.Select(c => new XElement("node",
    new XAttribute("guid", Guid.NewGuid()),
    new XAttribute("title", BuildTitle(c)),
    new XAttribute("isHidden", false))))


private string BuildTitle(CommuncationDetails c)
{
    var culturedDetails = c.CommunicationDetails.Where(x => x.CultureCode == culture).FirstOrDefault();

    if (culturedDetails == null || string.IsNullOrEmpty(culturedDetails.Title)) return string.Empty;

    return culturedDetails.Title.Substring(0, Math.Min(40, culturedDetails.Title.Length));
}