2

私はこのコードの平和を持っています。NULL例外を回避して、XMLの各レベルをチェックする必要があります。このコードを改善できますか?

private void GetFunctionsValues(XElement x)
    {
        if (x.Element("credentials") != null)
        {
            if (x.Element("credentials").Element("faccess") != null)
            {
                foreach (var access in x.Element("credentials").Element("faccess").Elements("access"))
                {
                    if (access.Attribute("db_id") != null)
                    {
                        if (int.Parse(access.Attribute("db_id").Value) == 19) FuncPlus = true;
                    }
                }
            }
        }
    }
4

8 に答える 8

5

ifネストされた2つを1つに折りたたむことができます。

if (x.Element("credentials") != null && x.Element("credentials").Element("faccess") != null )

最初のものがfalseと評価されると、2番目の実行が妨げられるため、null参照例外はありません。この動作は通常「短絡評価」と呼ばれます。プログラムはすぐにスキップできることを理解しif、残りの部分の評価を停止します。

于 2012-08-16T08:48:51.507 に答える
3

これが最も簡単な代替手段になると思います。

    private void GetFunctionsValues(XElement x)
    {
        var el = x.XPathSelectElement(@"credentials/faccess/access[@db_id=19]");
        if(el != null)
            FuncPlus = true;
    }

XPathSelectElementSystem.Xml.XPath名前空間で宣言されています。

于 2012-08-16T09:03:31.863 に答える
2

このようなコードを読みやすくするための拡張メソッドがあります。

 public static TResult Access<TSource, TResult>(
           this TSource obj, 
           Func<TSource, TResult> expression, 
           TResult defaultValue = default(TResult)) where TSource : class
    {
        if (obj == null)
        {
            return defaultValue;
        }

        return expression.Invoke(obj);
    }

そのような場合、あなたは流暢に書くことができますいくつかのプロパティにアクセスします:

var faccessElement = x
         .Access(y => y.Element("credentials"))
         .Access(y => y.Element("faccess"));
if (faccessElement != null) 
{
    //...
}
于 2012-08-16T09:13:59.643 に答える
1

if()ブール演算にはオペランドが評価される順序(左から右)が定義されているという事実だけで、いくつかのをマージできます。

これを書く代わりに:

if (condition_a)
    if (condition_b)
        action();

あなたは単にこれを使うことができます:

if (condition_a && condition_b)
     action();

オブジェクトが最初に存在することを確認してから、さらにチェックを実行してください。

于 2012-08-16T08:49:51.957 に答える
1

最初の2つを1つに結合し、属性の選択をループ内ifのクエリに入れることで、少なくとももう少しコンパクトにすることができます。foreach

private void GetFunctionsValues(XElement x) 
{ 
    if (x.Element("credentials") != null
        && x.Element("credentials").Element("faccess") != null) 
    { 
        foreach (var attribute in x.Element("credentials")
                                   .Element("faccess")
                                   .Elements("access")
                                   .Select(x => x.Attribute("db_id"))
                                   .Where(x => x != null)) 
        { 
            if (int.Parse(attribute.Value) == 19) FuncPlus = true; 
        } 
    } 
} 

最初の2つを1つに組み合わせることができる理由については、この回答を参照してくださいif

于 2012-08-16T08:49:56.447 に答える
1

それを改善し、2つを組み合わせるには、

private void GetFunctionsValues(XElement x)
{
    var credentialsElement = x.Element("credentials") ;
    if (credentialsElement != null && credentialsElement.Element("faccess") != null)
    {
         foreach (var access in credentialsElement.Element("faccess").Elements("access"))
         {
             if (access.Attribute("db_id") != null)
             {
                 if (int.Parse(access.Attribute("db_id").Value) == 19) FuncPlus = true;
             }
         }
     } 
}
于 2012-08-16T08:50:41.833 に答える
1

私はしばしば、覆瓦の代わりにreturnを使用すると、コードが読みやすくなることがわかります。

private void GetFunctionsValues(XElement x)
{
    if (x.Element("credentials") == null || x.Element("credentials").Element("faccess") == null) return;
    foreach (var access in x.Element("credentials").Element("faccess").Elements("access"))
    {
        if (access.Attribute("db_id") != null && int.Parse(access.Attribute("db_id").Value) == 19)
        {
            FuncPlus = true;
            return; // it seems we can leave now !
        }
    }
}

そして、条件が検証されたときに追加したリターンを見てください。反復を続行する必要はないと思います。

于 2012-08-16T08:51:08.480 に答える
1

それが私だったら、私はそれを次のように書くでしょう:

private void GetFunctionsValues(XElement x)
{
    if (x.Element("credentials") == null
    || x.Element("credentials").Element("faccess") == null)
       return;

    bool any = 
       x
       .Element("credentials")
       .Element("faccess")
       .Elements("access")
       .Where(access => access.Attribute("db_id") != null)
       .Any(access => int.Parse(access.Attribute("db_id").Value) == 19);

    if (any)
       FuncPlus = true;
}

注意すべき重要事項:

連続する2つifのsは、それらの式を。で結合することによって置き換えることができます&&。元:

if (test1)
   if (test2)

// becomes

if (text1 && test2)

aのforeach後にanを付けると、LINQクエリifに置き換えることができます。Where元:

foreach (var item in collection)
   if (item.SomeProperty == someValue)
      action(item);


// becomes

collection
.Where(item => item.SomeProperty == someValue)
.ForEach(action);

何らかのアクションを実行する前に行うテストは、過度のネストを避けるために、逆に記述した方がよい場合がよくあります。元:

if (test1)
   if (test2)
      if (test3)
         doSomething();

// becomes

if (!(test1 || test2 || test3))
   return;

doSomething();
于 2012-08-16T08:59:07.063 に答える