string.IsNullOrEmpty() 似乎不适用于类内类内的字符串
首先,我想我知道发生了什么事,但我想我应该把这个问题提出来进行一些讨论,看看除了我的想法之外是否有人对此有“答案”。因为,这对我来说完全没有意义。
我发现,当为异常创建错误日志时,我正在这样做,但它不起作用:
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 就足够了吗?如果我们有一个内部异常,我们总是会有一条与之相关的消息吗?
谢谢。
First off, I think I know what's going on, but I thought I'd bring this issue up here for some discussion and see if anyone has an "answer" to this other than what I'm thinking. Because, it doesn't completely make sense to me.
What I found is that when creating a error log for exceptions, I was doing this and it wasn't working:
catch( Exception ex )
{
LogException( ex.Message );
if ( !string.IsNullOrEmpty( ex.InnerException.Message ) )
{
LogInnerException( ex.InnerException.Message );
}
}
and lo and behold, when I ran this I'd often get a NullReferenceException. Huh?
I'm checking for null, right?
now, I have to use this:
if ( ex.InnerException != null && !string.IsNullOrEmpty( ex.InnerException.Message )
but that seems counter-intuitive and also counter productive. Because, heck, if I do this:
if ( !string.IsNullOrEmpty( null ) )
That doesn't give me any problems at all. And if ex.InnerException is null, then certainly ex.InnerException.Message is null, right?
Apparently not.
I wrote a complete console app that reproduces this. If you
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() { }
}
}
What I think is happening is that the code processes ex.InnerException.Message before trying to process the IsNullOrEmpty. Since ex.InnerException is null, we get an exception trying to access ex.InnerException.Message.
I'm wondering though, do I need the full check? Will the ex.InnerException != null be enough. If we have an inner exception, will we always have a message associated with it?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
当您调用
ex.InnerException.Message
时,不是消息为 null,而是InnerException
对象。可以这样想:
要完全匹配你想要做的事情,只需使用这个:
为了解决这个问题,我过去使用过这个方法:
When you call
ex.InnerException.Message
, it's not the message that is null, but rather thenInnerException
object.Think of it this way:
To match exactly what you want to do, just use this:
In order to solve this problem, I have used this method in the past:
如果
InnerException
为 null,则您无法访问其属性之一(在您的情况下为Message
)。这就是为什么你会得到异常,而且不可能有其他情况。尝试这样思考:
string.IsNullOrEmpty
如何知道您用来向其传递参数的表达式?对于函数来说,它只是一个参数。这两种形式是等效的,但也许第二种形式对您来说会更清楚:
希望这是清楚的:)
If
InnerException
is null you cannot access one of its properties (Message
in your case). This is why you get the exception, and it could not be otherwise.Try to think like this: how can
string.IsNullOrEmpty
know the expression you are using to pass it a parameter? For the function, it is just a parameter.These two forms are equivalent, but maybe the second will be clearer for you:
Hope this is clear :)
请记住,C# 中的执行顺序是在将参数发送到方法方法体(即压入堆栈)之前对参数进行求值。指令
string.IsNullOrEmpty(x)
将首先计算x
。就您而言,示例中的
x
是ex.InnerException.Message
。这是从左到右评估的。如果ex
或ex.InnerException
为 null,则抛出 NullReferenceException。这里有一种解决这个问题的方法,因为你知道
ex
永远不会为 null,它将检查 InnerException 的 Message 属性(如果有),或者检查 Message 的 Message 属性(如果没有 InnerException):想要首先检查是否存在
InnerException
,可以像这样完成:或者您想使用异常或内部异常消息,如果两者都存在,则优先使用 InnerException,使用这个:
Remember that the order of execution in C# is that parameters are evaluated before they're send through to the method method body (i.e., pushed on the stack). The instruction
string.IsNullOrEmpty(x)
will first evaluatex
.In your case,
x
in the example isex.InnerException.Message
. This is evaluated from left to right. If eitherex
, orex.InnerException
are null, a NullReferenceException is thrown.Here's a way to work around this, because you know that
ex
is never null, which will check the Message property of InnerException if there is any, or of Message if there is no InnerException:But you probably just want to check whether there is an
InnerException
in the first place and that can be done like so:Or you want to use either the exception or the inner exception message, with preference for InnerException if both are there, use this:
基本上,任何时候使用
.
都有可能出现空引用异常。这很痛苦,但是,是的,您需要检查InnerException
是否为 null。Basically, any time you use a
.
you've got a chance for a null reference exception. It's a pain, but yeah, you need to checkInnerException
for null.