.net 如果默认字符串为空,为什么不能使用String.Contains()?

e37o9pze  于 2023-10-21  发布在  .NET
关注(0)|答案(4)|浏览(185)

MSDN doc

public bool Contains(
    string value
)

返回值:true如果value参数出现在此字符串中,或者 value 为空字符串(“”);否则为false
异常:ArgumentNullExceptionvaluenull
范例:

string s = string.Empty; //or string s = "";
Console.WriteLine(s.Contains("Hello World!")); //output: False

如果我把它改成:

try
{
   string s = null; //or string s;
   Console.WriteLine(s.Contains("Hello World!"));
}
catch (Exception e)
{
   Console.WriteLine(e.Message);
}

它会抛出一个错误消息:Object reference not set to an instance of an object由于string没有来自Default Values Table (C# Reference)的默认值(如""),
请回到示例,如果我声明s,代码将工作:

string s = "";

现在,*Object s被设置为对象的示例 *。
所以我的问题是MSDN是否忘记了这样的事情:s不能为null
为了检查它,我试过:

string s = null;
Console.WriteLine(!string.IsNullOrEmpty(s) ? s.Contains("Hello World!") : false);

应该可以的

sg3maiej

sg3maiej1#

您使用示例更改了

myString.Contains(anotherString)

这里myString是调用方法Contains示例,而anotherString是传递给方法的。如果这个值是null,则该方法将抛出ArgumentNullException
另一方面,当将instance更改为null时,它肯定会导致NRE,因为您不能在空引用上调用任何成员。但是,如果将其设置为string.emptyContains将返回false,因为空字符串不包含 * 任何内容 *(特别是string.empty不包含"Hello World",但"Hello world"包含空字符串)。
因此,下面返回false

Console.WriteLine(string.Empty.Contains("Hello World"));

返回true

Console.WriteLine("Hello World".Contains(string.Empty));

无论如何,你要检查的是空字符串是否包含在任何其他字符串中:

var retVal = myString.Contains(string.empty);

返回true
myString.Contains(null)导致ArgumentNullException
在另一边,null.Contains(aString)通向NRE。

798qvoo8

798qvoo82#

新的编译器允许你简化条件检查。

string s = null;
Console.WriteLine(s?.Contains("Hello World!"));
e5nqia27

e5nqia273#

听起来这个问题更多的是关于 value 类型(不能为null)和 reference 类型(可以为null)之间的区别。在C#和其他OO语言中,它与内存处理有关。
您的MSDN文章中列出的值类型都具有已知的大小-例如。int将 * 始终 * 是32位大小等。在引擎盖下,这些都是structs。由于它们的大小是固定的,无论值是多少,C#都将它们存储在call stack上。由于null在定义上没有引用任何东西,因此它没有大小。一个有固定大小的东西同时也存在没有大小是没有意义的。
如果您仔细阅读MSDN上的string文档,您会发现string是一个 * 类 * 而不是结构。这是因为一个字符串可以是你喜欢的任何长度,所以它必须作为一个指针存储在堆上的一些数据。当你声明一个引用类型的变量时,它会在堆栈上创建一个指向堆上某个位置的指针,但是在你给予这个变量一个值之前,这个地址上不会有任何东西。**在此之前,该变量的指针是指向的,内存实际上不包含任何内容-即。null**并且尝试查找“Hello World!“什么都没有。空字符串仍然是字符串,但null实际上什么都不是。
这可能比您预期的更详细,但是了解一种语言的基本原则是很好的,即使您并不需要它们。This article是很值得一读,如果你想去更深入一点。null的想法可能是一个奇怪的概念,让你的头左右,但一旦你得到它的窍门,这一切都是有意义的,诚实!

guz6ccqo

guz6ccqo4#

如果你需要确保你的输出是bool(不是bool?nullable bool),以便能够在条件语句中使用它。您将需要使用简化的条件检查和非合并运算符。我在使用linq查询时遇到了这个问题,它不允许我使用bool?代替布尔值。相反,使用这样的代码:

List<string?> SL = new string?[] { null, "not null", "not null either", null, "null... just kidding" }.ToList();
string? result = SL.FirstOrDefault(s => s?.Contains("just") ?? false);
Console.WriteLine(result);

因为我的列表中的字符串是可空的,所以我的linq查询中的s也是可空的。因此Contains方法返回一个可空的bool,linq查询需要知道如何处理空结果。所以用??运算符我告诉它如果Contains方法返回null则返回false。
或者另一种优雅的方式是使用?在运行Contains方法之前对字符串执行?运算符。

string s = null;
Console.WriteLine((s ?? "").Contains("Hello World!"));

相关问题