检查字符串是空还是空的顺序?

时间:2015-01-31 10:36:34

标签: c#

对于我的编程考试,我必须为我编写的代码辩护。其中一条线是:

if(app.Logourl == "" || app.Logourl == null)

他问我null和空字符串之间是否有区别。我告诉他,区别在于null表示它没有指向任何东西,所以它没有实例化,但是空字符串是。

考试结束后,我走到他身边,问他是否正确,因为我看到他脸上的滑稽表情。他告诉我,他们的确是不同的,但我检查数值的顺序是不正确的。

现在几天后,我相信订单没有错。我是对的吗?

TL; DR

if(app.Logourl == "" || app.Logourl == null)

相当于

if(app.Logourl == null || app.Logourl == "")

5 个答案:

答案 0 :(得分:14)

你做的方式没问题,因为==的{​​{1}}超载调用String.Equals,允许System.String s。

这不是通用的,但是:如果您想检查字符串长度而不是使用null,那么您的第一个代码段将遇到麻烦:

== ""

而第二个没问题:

if(app.Logourl.Length == 0 || app.Logourl == null) // <<== Wrong!

原因是评估if(app.Logourl == null || app.Logourl.Length == 0) // <<== Correct ||运营商时出现短路:一旦他们知道结果(&& true||对于false)他们停止评估。在上面的第二个代码段中,如果&&app.Logourl,则表达式的后半部分将被忽略,因此null不会抛出空引用异常。

注意:为了识别这样的支票在各处发生,C#类库offers a convenience method for doing this check

app.Logourl.Length

答案 1 :(得分:2)

    private static bool IsNullOrEmpty(string s)
    {
        return s == null || s == "";

        /*
         Lets look behind the scenes here:
         =================================
        IL_0000: ldarg.0   => load s on the evaluation stack   
        IL_0001: brfalse.s IL_000f => GoTo label 'IL_000f' if loaded argument is null

        IL_0003: ldarg.0    => load s on the evaluation stack  
        IL_0004: ldstr ""   => load constant string "" to the evaluation stack
        IL_0009: call bool [mscorlib]System.String::op_Equality(string, string)
                              => Call String.Equality(string,string) with s and "" 
                                 loaded to the evalutation stack
                                 that will pop the two values compare them for equality and load the result.
                                 to the evaluation stack.                                     

        IL_000e: ret  => Return to the caller with equlity result on the evauation stack.

        IL_000f: ldc.i4.1 => Load constant value 1(4 byte which will represent "True") to the evaluation stack
                             and return to the caller.In our flow it's the case when s is null.
        IL_0010: ret 

         In Summary:
         ===========
        1.) IL instructions total code size 17 bytes.
        2.) Best case scenario execution path => 2 IL instructions.
        3.) Worst case scenario execution pat => 8 IL instructions.

        */
    }

    private static bool IsEmptyOrNull(string s)
    {
        return s == "" || s == null;

        /*
         Lets look behind the scenes here:
         =================================
         IL_0000: ldarg.0  => load s on the evaluation stack   
         IL_0001: ldstr "" => load constant string "" to the evaluation stack
         IL_0006: call bool [mscorlib]System.String::op_Equality(string, string)
         IL_000b: brtrue.s IL_0012

         IL_000d: ldarg.0 => load s on the evaluation stack   
         IL_000e: ldnull  => load constant null on the evaluation stack 
         IL_000f: ceq => Pop two loaded values compare and push the result back on the evaluation stack
         IL_0011: ret

         IL_0012: ldc.i4.1 => Load constant value 1(4 byte which will represent "True") to the evaluation stack
                             and return to the caller.In our flow it's the case when s is null.
         IL_0013: ret 

          In Summary:
         ===========
        1.) IL instructions total code size 20 bytes.
        2.) Best case scenario execution path => 6 IL instructions.
        3.) Worst case scenario execution path => 10 IL instructions.
     */

    }

结论:

仅通过IL发出的代码来判断  “if(app.Logourl ==”“|| app.Logourl == null)”  是“微观化”更好的表现明智:)

答案 2 :(得分:1)

不,没关系(在你的情况下)。

有一件事要知道,布尔运算符&&||是短路的,这意味着如果你有a || batrue ,然后b未被评估。

例如,

app.Logourl == null || app.Logourl == ""

如果app.Logourlnull,则app.Logourl == ""甚至不会被评估。

在你的情况下,无论你检查一个还是另一个,都没有什么区别。第一个或第一个。如果检查有所不同,那就很重要。

例如,

app.Logourl == null || app.Logourl.Equals("")

如果您执行了其他订单,则app.Logourlnull时会出现异常,因为您无法调用空引用的成员函数。


虽然我使用String.IsNullOrEmpty(app.Logourl),这是标准的lib。

答案 3 :(得分:1)

这只是一个评论。

在通常情况下,这无关紧要。但是可能会有副作用。以下是一个值得学习的简单示例:

static class Program
{
    static string Logourl
    {
        get
        {
            Console.WriteLine("getter runs");
            return null;
        }
    }

    static void Main()
    {
        if (Logourl == "" || Logourl == null)
        {
        }
    }
}

该程序将写:

getter runs
getter runs

如果您更换支票的顺序,getter runs只会打印一次。如果您将属性更改为return "";,则会相反。

当然,使用string.IsNullOrEmpry(Logurl)将始终只检索一次属性。

答案 4 :(得分:0)

当我确定我的对象是string时,我总是更喜欢以下内容:

    if (string.IsNullOrEmpty(yourString))
    {
        // this string is null or empty
    }

或者这个:

    if (string.IsNullOrWhiteSpace(yourString))
    {
        // this string is null or empty (or got only a space)
    }