10

From MSDN doc:

public bool Contains(
    string value
)

Return Value: true if the value parameter occurs within this string, or if value is the empty string (""); otherwise, false.

Exception: ArgumentNullException: value is null.

Example:

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

If I change it to:

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

It'll throw an error message: Object reference not set to an instance of an object since string doesn't have a default value (like "") from Default Values Table (C# Reference),

Please come back to the example, the code will work if I declare s:

string s = "";

Now, Object s is set to an instance of an object.

So, my question is: Does MSDN forgot something like: s cannot be null?

To check it, I've tried:

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

It should work.

Tân
  • 1
  • 13
  • 45
  • 86

3 Answers3

18

You changed the value with the instance.

myString.Contains(anotherString)

Here myString is the instance on which you call the method Contains, whereas anotherString is the value passed to the method. If this value is null the method will throw an ArgumentNullException.

When changing the instance to null on the other hand it surely leads to NRE as you can´t call any member on a null-reference. However if you set it to string.empty Contains will return false because the empty string does not contain anything (in particular string.empty does not contain "Hello World", however "Hello world" contains the empty string).

So the following returns false:

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

Whilst this returns true:

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

Anyway what you want to check is if the empty string IS contained in any other one:

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

Which should return true.

Furthermore myString.Contains(null) leads to ArgumentNullException

On the other side null.Contains(aString) leads to the NRE.

HimBromBeere
  • 32,045
  • 4
  • 46
  • 84
5

the new compilier allows you to do it with the condition check simplified.

string s = null;
Console.WriteLine(s?.Contains("Hello World!"));
Mike
  • 1,097
  • 11
  • 8
0

It sounds like this question is more about the difference between value types (which cannot be null) and reference types (which can be). In C# and other OO languages it's to do with memory handling.

The value types listed in your MSDN article are all of a known size - e.g. int will always be 32 bits in size etc. Under the hood, these are all structs. As they are of fixed size regardless of the value, C# stores them on the call stack. As null by definition doesn't refer to anything, it has no size. It doesn't make sense for something that exists with a fixed size to also exist with no size.

If you read the documentation for string on MSDN a little closer, you'll see the string is a class not a struct. This is because a string can be of any length you like, so it has to be stored as a pointer to some data on the heap. When you declare a reference type variable, it creates a pointer on the stack to a location on the heap, but there won't be anything at that address until you give that variable a value. Until then, the pointer for that variable is pointing and memory containing literally nothing - i.e. null and it doesn't make sense to try to find "Hello World!" in nothing. An empty string is still a string, but null is literally nothing.

This is probably more detail than you were expecting, but it's good to have an appreciation of the underlying principles of a language, even if you don't need them day to day. This article is well worth a read if you want to go a little more in depth. The idea of null can be a weird concept to get your head around, but once you get the hang of it, it all makes sense, honest!

Mourndark
  • 2,192
  • 3
  • 24
  • 42
  • Oh. Sorry. But I haven't read any document yet which says *the `string` is a class not a struct*. I agree with you that `string` is a reference type which is stored in Heap. But if `string` is a `class`, I can declare property for a `string`, can't I? Maybe I don't understand you mean. – Tân Nov 27 '15 at 10:41
  • It doesn't explicitly say it, but if you look at the syntax for [string](https://msdn.microsoft.com/en-us/library/system.string.aspx) and [int](https://msdn.microsoft.com/en-us/library/system.int32.aspx), one is a `class` and one is a `struct`. As for properties, the `string` class has two properties, `Length` and `Chars`, however they're defined so that you can only get their values, not set them - that wouldn't make sense! – Mourndark Nov 27 '15 at 10:48
  • `string` and `class` are 2 objects. It's not for `struct` and `int`. `struct` and `int` are value types, not reference types. You cannot compare them. – Tân Nov 27 '15 at 10:56