c# - What is a NullReferenceException, and how do I fix it? -
i have code , when executes, throws nullreferenceexception
, saying:
object reference not set instance of object.
what mean, , can it?
what cause?
bottom line
you trying use null
(or nothing
in vb.net). means either set null
, or never set @ all.
like else, null
gets passed around. if null
in method "a", method "b" passed null
to method "a".
the rest of article goes more detail , shows mistakes many programmers make can lead nullreferenceexception
.
more specifically
the runtime throwing nullreferenceexception
always means same thing: trying use reference, , reference not initialized (or once initialized, no longer initialized).
this means reference null
, , cannot access members (such methods) through null
reference. simplest case:
string foo = null; foo.toupper();
this throw nullreferenceexception
@ second line because can't call instance method toupper()
on string
reference pointing null
.
debugging
how find source of nullreferenceexception
? apart looking @ exception itself, thrown @ location occurs, general rules of debugging in visual studio apply: place strategic breakpoints , inspect variables, either hovering mouse on names, opening (quick)watch window or using various debugging panels locals , autos.
if want find out reference or isn't set, right-click name , select "find references". can place breakpoint @ every found location , run program debugger attached. every time debugger breaks on such breakpoint, need determine whether expect reference non-null, inspect variable , and verify points instance when expect to.
by following program flow way, can find location instance should not null, , why isn't set.
examples
some common scenarios exception can thrown:
generic
ref1.ref2.ref3.member
if ref1 or ref2 or ref3 null, you'll nullreferenceexception
. if want solve problem, find out 1 null rewriting expression simpler equivalent:
var r1 = ref1; var r2 = r1.ref2; var r3 = r2.ref3; r3.member
specifically, in httpcontext.current.user.identity.name
, httpcontext.current
null, or user
property null, or identity
property null.
class instances
when creating variable of reference (class) type, default set null
.
public class book { public string title { get; set; } } public class example { public void foo() { book b1; string title = b1.title; // never initialized b1 variable. // there no book title from. } }
class type variables must either initialized or set existing class instance. initialization done using new
keyword.
book b1 = new book();
indirect
public class person { public int age { get; set; } } public class book { public person author { get; set; } } public class example { public void foo() { book b1 = new book(); int authorage = b1.author.age; // never initialized author property. // there no person age from. } }
if want avoid child (person) null reference, initialize in parent (book) object's constructor.
the same applies nested object initializers:
book b1 = new book { author = { age = 45 } };
while new
keyword used, creates new instance of book
, not new instance of person
, author
property still null
.
array
int[] numbers = null; int n = numbers[0]; // numbers null. there no array index.
array elements
person[] people = new person[5]; people[0].age = 20 // people[0] null. array allocated not // initialized. there no person set age for.
jagged arrays
long[][] array = new long[1][]; array[0][0] = 3; // null because first dimension yet initialized. // use array[0] = new long[2]; first.
collection/list/dictionary
dictionary<string, int> agesfornames = null; int age = agesfornames["bob"]; // agesfornames null. // there no dictionary perform lookup.
range variable (indirect/deferred)
public class person { public string name { get; set; } } var people = new list<person>(); people.add(null); var names = p in people select p.name; string firstname = names.first(); // exception thrown here, occurs // on line above. "p" null because // first element added list null.
events
public class demo { public event eventhandler statechanged; protected virtual void onstatechanged(eventargs e) { statechanged(this, e); // exception thrown here // if no event handlers have been attached // statechanged event } }
bad naming conventions:
if named fields differently locals, might have realized never initialized field.
public class form1 { private customer customer; private void form1_load(object sender, eventargs e) { customer customer = new customer(); customer.name = "john"; } private void button_click(object sender, eventargs e) { messagebox.show(customer.name); } }
this can solved following convention prefix fields underscore:
private customer _customer;
asp.net page life cycle:
public partial class issues_edit : system.web.ui.page { protected testissue myissue; protected void page_load(object sender, eventargs e) { if (!ispostback) { // called on first load, not when button clicked myissue = new testissue(); } } protected void savebutton_click(object sender, eventargs e) { myissue.entry = "nullreferenceexception here!"; } }
asp.net session values
// if "firstname" session value has not yet been set, // line throw nullreferenceexception string firstname = session["firstname"].tostring();
asp.net mvc empty view models
if exception occurs when referencing property of @model
in asp.net mvc view, need understand model
gets set in action method, when return
view. when return empty model (or model property) controller, exception occurs when views access it:
// controller public class restaurant:controller { public actionresult search() { return view(); // forgot provide model here. } } // razor view @foreach (var restaurantsearch in model.restaurantsearch) // throws. { } <p>@model.somepropertyname</p> <!-- throws -->
wpf control creation order , events
wpf controls created during call initializecomponent
in order appear in visual tree. nullreferenceexception
raised in case of early-created controls event handlers, etc. , fire during initializecomponent
reference late-created controls.
for example :
<grid> <!-- combobox declared first --> <combobox name="combobox1" margin="10" selectedindex="0" selectionchanged="combobox1_selectionchanged"> <comboboxitem content="item 1" /> <comboboxitem content="item 2" /> <comboboxitem content="item 3" /> </combobox> <!-- label declared later --> <label name="label1" content="label" margin="10" /> </grid>
here combobox1
created before label1
. if combobox1_selectionchanged
attempts reference `label1, not yet have been created.
private void combobox1_selectionchanged(object sender, selectionchangedeventargs e) { label1.content = combobox1.selectedindex.tostring(); // nullreference here!! }
changing order of declarations in xaml (i.e., listing label1
before combobox1
, ignoring issues of design philosophy, @ least resolve nullreferenceexception
here.
cast as
var mything = someobject thing;
this doesn't throw invalidcastexception returns null
when cast fails (and when someobject null). aware of that.
linq firstordefault() , singleordefault()
the plain versions first()
, single()
throw exceptions when there nothing. "ordefault" versions return null in case. aware of that.
foreach
foreach
throws when try iterate null collection. caused unexpected null
result methods return collections.
list<int> list = null; foreach(var v in list) { } // exception
more realistic example - select nodes xml document. throw if nodes not found initial debugging shows properties valid:
foreach (var node in mydata.myxml.documentnode.selectnodes("//data"))
ways avoid
explicitly check null
, ignore null values.
if expect reference null, can check being null
before accessing instance members:
void printname(person p) { if (p != null) { console.writeline(p.name); } }
explicitly check null
, provide default value.
methods call expect return instance can return null
, example when object being sought cannot found. can choose return default value when case:
string getcategory(book b) { if (b == null) return "unknown"; return b.category; }
explicitly check null
method calls , throw custom exception.
you can throw custom exception, catch in calling code:
string getcategory(string booktitle) { var book = library.findbook(booktitle); // may return null if (book == null) throw new booknotfoundexception(booktitle); // custom exception return book.category; }
use debug.assert
if value should never null
, catch problem earlier exception occurs.
when know during development method maybe can, never should return null
, can use debug.assert()
break possible when occur:
string gettitle(int knownbookid) { // know should never return null. var book = library.getbook(knownbookid); // exception occur on next line instead of @ end of method. debug.assert(book != null, "library didn't return book known book id."); // other code return book.title; // never throw nullreferenceexception in debug mode. }
though check will not end in release build, causing throw nullreferenceexception
again when book == null
@ runtime in release mode.
use getvalueordefault()
nullable value types provide default value when null
.
datetime? appointment = null; console.writeline(appointment.getvalueordefault(datetime.now)); // display default value provided (datetime.now), because appointment null. appointment = new datetime(2022, 10, 20); console.writeline(appointment.getvalueordefault(datetime.now)); // display appointment date, not default
use null coalescing operator: ??
[c#] or if()
[vb].
the shorthand providing default value when null
encountered:
iservice createservice(ilogger log, int32? frobpowerlevel) { var serviceimpl = new myservice(log ?? nulllog.instance); // note above "getvalueordefault()" can rewritten use // coalesce operator: serviceimpl.frobpowerlevel = frobpowerlevel ?? 5; }
use null condition operator: ?.
(available in c# 6 , vb.net 14):
this called safe navigation or elvis (after shape) operator. if expression on left side of operator null, right side not evaluated, , null returned instead. means cases this:
var title = person.title.toupper();
if person not have title, throw exception because trying call toupper
on property null value.
in c# 5 , below, can guarded with:
var title = person.title == null ? null : person.title.toupper();
now title variable null instead of throwing exception. c# 6 introduces shorter syntax this:
var title = person.title?.toupper();
this result in title variable being null
, , call toupper
not made if person.title
null
.
of course, still have check title
null or use null condition operator null coalescing operator (??
) supply default value:
// regular null check int titlelength = 0; if (title != null) titlelength = title.length; // if title null, throw nullreferenceexception // combining `?` , `??` operator int titlelength = title?.length ?? 0;
Comments
Post a Comment