string.IsNullOrEmpty()似乎不能处理类中类的字符串

Dan*_*7el 2 .net c# string nullreferenceexception isnullorempty

首先,我想我知道发生了什么,但我想我会把这个问题带到这里进行一些讨论,看看是否有人对这个问题有"回答",而不是我在想什么.因为,这对我来说并不完全有意义.

我发现在为异常创建错误日志时,我这样做并且它无法正常工作:

catch( Exception ex )
{
   LogException( ex.Message );
   if ( !string.IsNullOrEmpty( ex.InnerException.Message ) )
   {
      LogInnerException( ex.InnerException.Message );
   }
}
Run Code Online (Sandbox Code Playgroud)

瞧,当我跑这个时,我经常得到一个NullReferenceException.咦?

我正在检查null,对吗?

现在,我必须使用这个:

   if ( ex.InnerException != null && !string.IsNullOrEmpty( ex.InnerException.Message ) 
Run Code Online (Sandbox Code Playgroud)

但这似乎是违反直觉的,也会产生反作用.因为,如果我这样做:

   if ( !string.IsNullOrEmpty( null ) )
Run Code Online (Sandbox Code Playgroud)

这根本不会给我任何问题.如果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() { }
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为发生的是代码在尝试处理IsNullOrEmpty之前处理ex.InnerException.Message.由于ex.InnerException为null,因此我们在尝试访问ex.InnerException.Message时遇到异常.

我想知道,我需要全面检查吗?请问ex.InnerException!= null是否足够.如果我们有内部异常,我们是否总会有与之关联的消息?

谢谢.

Joh*_*zen 7

当你调用时ex.InnerException.Message,它不是消息,而是null,而不是InnerException对象.

想一想:

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

要准确匹配您要执行的操作,请使用以下命令:

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

为了解决这个问题,我过去曾使用过这种方法:

__PRE__

public Exception GetInnermost(Exception ex)
{
    while (ex.InnerException != null) ex = ex.InnerException;
    return ex;
}

  • @Abel:为什么递归有帮助?这个循环肯定比非尾调用体系结构上的递归更快,并且相当于尾调用优化系统. (2认同)