3

まず、何が起こっているのかはわかっていると思いますが、この問題をここで取り上げて議論し、私が考えている以外の誰かがこれに対する「答え」を持っているかどうかを確認したいと思いました。なぜなら、それは私には完全には意味がありません。

私が見つけたのは、例外のエラーログを作成するときに、これを実行していて、機能していなかったことです。

catch( Exception ex )
{
   LogException( ex.Message );
   if ( !string.IsNullOrEmpty( ex.InnerException.Message ) )
   {
      LogInnerException( ex.InnerException.Message );
   }
}

そして、見よ、これを実行すると、NullReferenceExceptionが発生することがよくありました。は?

nullをチェックしていますよね?

今、私はこれを使用する必要があります:

   if ( ex.InnerException != null && !string.IsNullOrEmpty( ex.InnerException.Message ) 

しかし、それは直感に反し、生産性にも反しているようです。なぜなら、私がこれを行うと、一体、次のようになります。

   if ( !string.IsNullOrEmpty( null ) )

それは私に何の問題も与えません。そして、ex.InnerExceptionがnullの場合、確かにex.InnerException.Messageはnullですよね?

どうやらそうではありません。

これを再現する完全なコンソールアプリを作成しました。もし、あんたが

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace stringisnullorempty
{
    class Program
    {
        static void Main( string[] args )
        {
            if ( !string.IsNullOrEmpty( null ) )
            {
                Console.WriteLine( "Ha ha ha, right...." );
            }

            MyBClass bClass = new MyBClass();
            bClass.BClassName = "Some B Class Name";
            if ( !string.IsNullOrEmpty( bClass.AClass.AString ) ) //<== Exception occurs here.
            {
                Console.WriteLine( bClass.AClass.AString );
            }
        }
    }

    public class MyAClass
    {
        private string aString;
        public string AString
        {
            get
            {
                return aString;
            }
            set
            {
                aString = value;
            }
        }

        private int aValue;
        public int AValue
        {
            get
            {
                return aValue;
            }
            set
            {
                aValue = value;
            }
        }

        public MyAClass() { }
    }

    public class MyBClass
    {
        private MyAClass aClass;
        public MyAClass AClass
        {
            get
            {
                return aClass;
            }
            set
            {
                aClass = value;
            }
        }

        private string bClassName;
        public string BClassName
        {
            get
            {
                return bClassName;
            }
            set
            {
                bClassName = value;
            }
        }
        public MyBClass() { }
    }
}

私が起こっていると思うのは、IsNullOrEmptyを処理しようとする前に、コードがex.InnerException.Messageを処理することです。ex.InnerExceptionがnullであるため、ex.InnerException.Messageにアクセスしようとすると例外が発生します。

でも気になりますが、完全なチェックが必要ですか?ex.InnerException!=nullで十分でしょうか。内部例外がある場合、常にそれに関連付けられたメッセージがありますか?

ありがとう。

4

4 に答える 4

7

を呼び出すときex.InnerException.Message、nullであるのはメッセージではなく、InnerExceptionオブジェクトです。

このように考えてください:

string temp = ex.InnerException.Message
              //               ^ the error is on this dot.
if (string.IsNullOrEmpty(temp))
{
    ...
}

やりたいことを正確に一致させるには、次を使用します。

catch (Exception ex)  // PLEASE catch something more specific.
{
   LogException(ex.Message);
   if (ex.InnerException != null)
   {
      LogInnerException(ex.InnerException.Message);
   }
}

この問題を解決するために、私は過去にこの方法を使用しました:

public Exception GetInnermost(Exception ex)
{{
    while(ex.InnerException!= null)ex = ex.InnerException;
    元を返す;
}

ex.GetBaseException()
于 2011-03-11T13:54:22.327 に答える
0

C#での実行順序は、パラメーターがメソッドメソッド本体に送信される前に(つまり、スタックにプッシュされる前に)評価されることを忘れないでください。命令string.IsNullOrEmpty(x)は最初にを評価しxます。

あなたの場合、x例ではex.InnerException.Messageです。これは左から右に評価されます。ex、またはがnullの場合ex.InnerException、NullReferenceExceptionがスローされます。

これを回避する方法は次のとおりですex。これはnullになることはないため、InnerExceptionがある場合はそのMessageプロパティをチェックし、InnerExceptionがない場合はMessageプロパティをチェックします。

if(string.IsNullOrEmpty((ex.InnerException ?? ex).Message))
{
    // .. do something 
}

しかし、おそらくInnerException最初にが存在するかどうかを確認したいだけで、それは次のように実行できます。

if(ex.InnerException != null) { ... }

または、例外または内部例外メッセージのいずれかを使用し、両方が存在する場合はInnerExceptionを優先して、次を使用します。

string exceptionMessage = (ex.InnerException ?? ex).Message;
于 2011-03-11T14:02:48.440 に答える
0

nullの場合InnerException、そのプロパティの1つにアクセスできません(Messageあなたの場合)。これが例外を受け取る理由であり、そうでない場合はそうではありません。

次のように考えてみてくださいstring.IsNullOrEmpty。パラメータを渡すために使用している式をどのように知ることができますか?関数の場合、これは単なるパラメーターです。

これらの2つの形式は同等ですが、おそらく2番目の形式の方が明確です。

string.IsNullOrEmpty( ex.InnerException.Message ); // exception here

string test = ex.InnerException.Message; // exception HERE
string.IsNullOrEmpty(test);

これが明確であることを願っています:)

于 2011-03-11T13:58:37.547 に答える
0

基本的に、を使用するときはいつでも. 、null参照例外が発生する可能性があります。InnerException苦痛ですが、ええ、 nullをチェックする必要があります。

于 2011-03-11T14:14:01.953 に答える