2016-09-13 20 views
0

ラムダ式が短い場合は2回書くのを避ける方法はありますか?私はこの状況で常に自分自身を見つけ、私が知っている唯一の方法はそれをもう一度書くことです!Short Ifでの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)))) 
+6

のようなものに終わるだろう。Title'が起こるのを待っ 'NullReferenceException'です。 – spender

答えて

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

リファクタリングで最初刺すだろう。

ラムダを1回呼び出すだけで最大長になるように文字列を拡張する方法もありますが、

だから、 `FirstOrDefault()は` `null`なので、` FirstOrDefault()を返すことができることを考えると、この

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

多くの正解が与えられましたが、私はそれを扱う代理関数をどのように作成するのが好きでした。 – EGN

+0

@EGNコードの繰り返しはなくなりました。疑いもなく、元のものが大きく改善されました。しかし、 'FirstOrDefault()'が2回呼び出されるため、実行時の繰り返しはどこにもありませんでした。 – dasblinkenlight

+0

拡張メソッドではありません。それは連鎖する。 – Tim

0

はい、あなたはstringであるという事実から恩恵を受けることができIEnumerable<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が発生するのを待っています。

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拡張メソッドを処理してください。

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)); 
} 
関連する問題