System.NullReferenceException
The exception that is thrown when there is an attempt to dereference a null object reference.
Minimum version: >= 1.1 >= Core 1.0
Statistics
How to handle it
try
{
}
catch (System.NullReferenceException e)
{
}
try
{
}
catch (System.NullReferenceException e) when (e.Message.Contains("something"))
{
}
try
{
}
catch (System.NullReferenceException e) when (LogException(e))
{
}
private static bool LogException(Exception e)
{
logger.LogError(...);
return false;
}
How to avoid it
Beforestring s = null;
try
{
s.ToString();
}
catch (NullReferenceException e)
{
}
After
string s = "Hello World";
if (s != null)
{
s.ToString();
}
Links
YouTube videos
Possible fixes from StackOverflow
I'm not sure what you've tried that is giving you trouble, but you can simply pass in a lambda as the first argument to Assert.Throws. Here's one from one of my tests that passes:
Assert.Throws<ArgumentException>(() => pointStore.Store(new[] { firstPoint }));
Okay, that example may have been a little verbose. Suppose I had a test
[Test]
[ExpectedException("System.NullReferenceException")]
public void TestFoo()
{
MyObject o = null;
o.Foo();
}
which would pass normally because o.Foo()
would raise a null reference exception.
You then would drop the ExpectedException
attribute and wrap your call to o.Foo()
in an Assert.Throws
.
[Test]
public void TestFoo()
{
MyObject o = null;
Assert.Throws<NullReferenceException>(() => o.Foo());
}
Assert.Throws
"attempts to invoke a code snippet, represented as a delegate, in order to verify that it throws a particular exception." The () => DoSomething()
syntax represents a lambda, essentially an anonymous method. So in this case, we are telling Assert.Throws
to execute the snippet o.Foo()
.
So no, you don't just add a single line like you do an attribute; you need to explicitly wrap the section of your test that will throw the exception, in a call to Assert.Throws
. You don't necessarily have to use a lambda, but that's often the most convenient.
Because the language specification expects an expression of type System.Exception
there (therefore, null
is a valid in that context) and doesn't restrict this expression to be non-null. In general, there's no way it could detect whether the value of that expression is null
or not. It would have to solve the halting problem. The runtime will have to deal with the null
case anyway. See:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
They could, of course, make the specific case of throwing the null
literal invalid but that wouldn't help much, so why waste specification space and reduce consistency for little benefit?
Disclaimer (before I get slapped by Eric Lippert): This is my own speculation about the reasoning behind this design decision. Of course, I haven't been in the design meeting ;)
The answer to your second question, whether an expression variable caught within a catch clause can ever be null: While the C# specification is silent about whether other languages can cause a null
exception to be propagated, it does define the way exceptions are propagated:
The catch clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. The first catch clause that specifies the exception type or a base type of the exception type is considered a match. A general catch clause is considered a match for any exception type. [...]
For null
, the bold statement is false. So, while purely based on what the C# spec says, we can't say the underlying runtime won't ever throw null, we can be sure that even if that's the case, it'll be only handled by the generic catch {}
clause.
For C# implementations on the CLI, we can refer to the ECMA 335 specification. That document defines all exceptions that the CLI throws internally (none of which are null
) and mentions that user defined exception objects are thrown by the throw
instruction. The description for that instruction is virtually identical to C# throw
statement (except that it doesn't restrict the type of the object to System.Exception
):
Description:
The
throw
instruction throws the exception object (typeO
) on the stack and empties the stack. For details of the exception mechanism, see Partition I.
[Note: While the CLI permits any object to be thrown, the CLS describes a specific exception class that shall be used for language interoperability. end note]Exceptions:
System.NullReferenceException
is thrown ifobj
isnull
.Correctness:
Correct CIL ensures that object is always either
null
or an object reference (i.e., of typeO
).
I believe these are sufficient to conclude caught exceptions are never null
.
The correct way in .NET 4.0 is:
if (String.IsNullOrWhiteSpace(strSearch))
The String.IsNullOrWhiteSpace
method used above is equivalent to:
if (strSearch == null || strSearch == String.Empty || strSearch.Trim().Length == 0)
// String.Empty is the same as ""
Reference for IsNullOrWhiteSpace method
http://msdn.microsoft.com/en-us/library/system.string.isnullorwhitespace.aspx
Indicates whether a specified string is Nothing, empty, or consists only of white-space characters.
In earlier versions, you could do something like this:
if (String.IsNullOrEmpty(strSearch) || strSearch.Trim().Length == 0)
The String.IsNullOrEmpty
method used above is equivalent to:
if (strSearch == null || strSearch == String.Empty)
Which means you still need to check for your "IsWhiteSpace" case with the .Trim().Length == 0
as per the example.
Reference for IsNullOrEmpty method
http://msdn.microsoft.com/en-us/library/system.string.isnullorempty.aspx
Indicates whether the specified string is Nothing or an Empty string.
Explanation:
You need to ensure strSearch
(or any variable for that matter) is not null
before you dereference it using the dot character (.
) - i.e. before you do strSearch.SomeMethod()
or strSearch.SomeProperty
you need to check that strSearch != null
.
In your example you want to make sure your string has a value, which means you want to ensure the string:
- Is not null
- Is not the empty string (
String.Empty
/""
) - Is not just whitespace
In the cases above, you must put the "Is it null?" case first, so it doesn't go on to check the other cases (and error) when the string is null
.
First off, let me point out that "fire and forget" is almost always a mistake in ASP.NET applications. "Fire and forget" is only an acceptable approach if you don't care whether DeleteFooAsync
actually completes.
If you're willing to accept that limitation, I have some code on my blog that will register tasks with the ASP.NET runtime, and it accepts both synchronous and asynchronous work.
You can write a one-time wrapper method for logging exceptions as such:
private async Task LogExceptionsAsync(Func<Task> code)
{
try
{
await code();
}
catch(Exception exception)
{
m_log.Error("Call failed: " + exception.ToString());
}
}
And then use the BackgroundTaskManager
from my blog as such:
BackgroundTaskManager.Run(() => LogExceptionsAsync(() => DeleteFooAsync()));
Alternatively, you can keep TaskScheduler.UnobservedTaskException
and just call it like this:
BackgroundTaskManager.Run(() => DeleteFooAsync());
Other answers suggest this is an issue with your startup project.
As your project is a library, you could try setting your unit test project as your startup project per this answer.
You could also try setting the default project in Package Manager Console to your library project per the accepted answer here.
You might run into issues with where the migrations are created. If you need further control, in EF6 there are various arguments you can use with Enable-Migrations
as detailed in this answer but I don't have enough knowledge in this area to guide you further. You might need to do some reading.
Source: Stack Overflow