string.IsNullOrEmpty () не похоже на работу над строкой в классе в классе

2

Во-первых, я думаю, что знаю, что происходит, но я подумал, что приведу эту проблему для обсуждения и посмотрю, есть ли у кого-то ответ на этот вопрос, кроме того, о чем я думаю. Потому что это мне не совсем понятно.

Я обнаружил, что при создании журнала ошибок для исключений я делал это, и он не работал:

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() { }
    }
}

Я думаю, что происходит, что код обрабатывает ex.InnerException.Message перед попыткой обработать IsNullOrEmpty. Поскольку ex.InnerException имеет значение null, мы получаем исключение, пытающееся получить доступ к ex.InnerException.Message.

Мне интересно, нужна ли мне полная проверка? Будет достаточно ex.InnerException!= Null. Если у нас есть внутреннее исключение, всегда ли у нас есть сообщение, связанное с ним?

Спасибо.

Теги:
string
nullreferenceexception

4 ответа

7
Лучший ответ

Когда вы вызываете ex.InnerException.Message, это не сообщение, которое является нулевым, а скорее 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;
    return ex;
}
С >
ex.GetBaseException()
  • 1
    Вместо вашего метода GetInnermost вы можете использовать Exception.GetBaseException() .
  • 0
    @adrian: Ах, круто, я не знал, что это было.
Показать ещё 3 комментария
0

Если InnerException равно null, вы не можете получить доступ к одному из своих свойств (Message в вашем случае). Вот почему вы получаете исключение, и это не могло быть иначе.

Попробуйте подумать так: как string.IsNullOrEmpty знать выражение, которое вы используете, чтобы передать ему параметр? Для функции это просто параметр.

Эти две формы эквивалентны, но, возможно, второе будет более ясным для вас:

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

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

Надеюсь, что это ясно:)

0

Помните, что порядок выполнения в С# заключается в том, что параметры оцениваются до того, как они будут отправлены в тело метода метода (т.е. нажаты на стек). Команда string.IsNullOrEmpty(x) сначала оценит x.

В вашем случае x в этом примере ex.InnerException.Message. Это оценивается слева направо. Если либо ex, либо ex.InnerException равны нулю, генерируется исключение NullReferenceException.

Здесь вы можете обойти это, потому что знаете, что ex никогда не имеет значения null, которое проверяет свойство Message InnerException, если оно есть, или Message, если нет InnerException:

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

Но вы, вероятно, просто хотите проверить, есть ли InnerException в первую очередь, и это можно сделать так:

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

Или вы хотите использовать исключение или внутреннее сообщение об исключении, предпочитая InnerException, если они есть, используйте это:

string exceptionMessage = (ex.InnerException ?? ex).Message;
0

В принципе, в любое время, когда вы используете ., у вас есть шанс на исключение нулевой ссылки. Это боль, но да, вам нужно проверить InnerException на null.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню