La NullReferenceException
en Visual Basic no es diferente a la de C#. Después de todo, ambos reportan la misma excepción definida en el .Net Framework en la que ambos lenguajes están basados. Las causas que pueden ser exclusivas de Visual Basic son pocas (quizá solo una).
Esta respuesta usará los términos, sintaxis y contexto de Visual Basic. Los ejemplos utilizados estan extraidos de un gran número de antiguas preguntas en Stack Overflow. De esta manera se maximiza su relevancia, utilizando la clase de situaciones que a menudo surgen en los posts. También se adjunta algunas explicaciones mas para aquellos que quizá las necesiten. Un ejemplo similar al tuyo es muy probable que se encuentre aqui.
Notas:
- Esto es una respuesta conceptual: no hay nigún código que puedas copiar y pegar en tu proyecto. De lo que se trata es de ayudarte a entender que causa una
NullReferenceException
(NRE), cómo encontrarla, cómo solucionarla, y cómo evitarla. Una NRE puede tener muchas causas así que no esperes encontrar aquí todas ellas.
- Los ejemplos (de los posts en Stack Overflow) no siempre muestran la mejor manera de hacer algo para empezar.
- Normalmente usaremos la solución mas sencilla.
Significado Básico
El mensaje "Referencia a objeto no establecida como instancia de un objeto"
significa que estás intentando utilizar un objeto que no ha sido inicializado. Esto se puede reducir a una de estas causas:
- En tu código has declarado una variable de objeto, pero no la has inicializado (no has creado una instancia o 'instanciado')
- Algo que en tu código se asumía que inicializaría un objeto, no lo hizo
- Quizá otra parte del código invalidó un objeto que todavía estaba en uso prematuramente
Encontrando la causa
Partiendo de que el problema es una referencia de objeto que es Nothing
, la respuesta es examinar los objetos para encontrar cual de ellos es el problema, para a continuación determinar porqué no esta inicializado. Mantén el cursor del ratón encima de las variables y Visual Studio (VS) te mostrará sus valores - el culpable será Nothing
.
Además deberías eliminar cualquier bloque Try/Catch de las partes relevantes de tu código, especialmente aquello que tienen vacío el bloque Catch. Esto hará que tu código falle cuando trate de usar un objeto que es Nothing
. Esto es lo que quieres, ya que así identificarás la localización exacta del problema, permitiéndote identificar que objeto es el causante.
Un MsgBox
en el bloque Catch que muestre Error en...
es de muy poca ayuda. Este método de capturar excepciones provoca ademas muy malas preguntas en Stack Overflow, ya que no puedes describir la excepción real, que objeto la provoca y ni siquiera la línea de código donde ha ocurrido.
También puedes utilizar la ventana Variables Locales
(Depurar -> Ventanas -> Variables locales) para examinar tus objetos.
Una vez sepas cual es el problema y donde está, normalmente es muy sencillo de solucionarlo y es más rápido que añadir una nueva pregunta.
Ver también:
Ejemplos y soluciones
Objetos de Clase / Creando una Instancia
Dim reg As Registradora
...
TextBox1.Text = reg.Cantidad ' NRE
El problema es que Dim
no crea un objeto de tipo Registradora
; sólo declara una variable llamada reg
de ese Tipo. Declarar una variable de objeto y crear una instancia son dos cosas diferentes.
Solución
El operador New
es el que se usa normalmente para crear la instancia cuando declaras el objeto:
Dim reg As New Registradora ' [New] crea la instancia, invoca el constructor
' Otra forma mas larga y explícita:
Dim reg As Registradora = New Registradora
Cuando la instancia debe crearse mas tarde:
Private reg As Registradora ' Declaración
...
reg = New Registradora() ' Creamos la instancia
Nota: No uses Dim
de nuevo en un procedimiento, incluyendo el constructor (Sub New
):
Private reg As Registradora
'...
Public Sub New()
'...
Dim reg As New Registradora
End Sub
Esto creará una variable local, reg
, que existe sólo en este contexto (sub). La variable reg
que tiene como ámbito
el módulo y que usarás en todos los demás sitios permanece como Nothing
.
Olvidarse del operador New
es la causa nº 1 de las preguntas sobre NullReferenceExceptions
en la preguntas de Stack Overflow revisadas.
Visual Basic intenta hacer que el proceso sea claro usando repetidamente New
: Usando el operador New
creas un nuevo objeto y llama a Sub New
-- el constructor -- donde tu objeto puede realizar cualquier otra inicialización.
Para dejar esto claro, Dim
(o Private
) sólo declara una variable y su Type
(tipo). El alcance de la variable - si existe para todo el modulo/clase o si es local en un procedimiento - se determina por donde es declarada. Private | Friend | Public
define el nivel de acceso, no su Alcance.
Para más información,ver:
Arrays
Los Arrays también deben ser instanciados:
Private arr as String()
Este array solo ha sido declarado, no creado. Hay varias maneras de inicializar un array:
Private arr as String() = New String(10){}
' or
Private arr() As String = New String(10){}
' Para un array local (en un procedimiento) y usando 'Option Infer':
Dim arr = New String(10) {}
Nota: A partir de VS 2010, cuando se inicializa un array local usando un literal y Option Infer
, los elementos As <Type>
y New
son opcionales:
Dim myDbl As Double() = {1.5, 2, 9.9, 18, 3.14}
Dim myDbl = New Double() {1.5, 2, 9.9, 18, 3.14}
Dim myDbl() = {1.5, 2, 9.9, 18, 3.14}
El tipo y tamaño del array size se infieren de los datos que son asignados. Las declaraciones a nivel de Clase/Modulo todavía requieren As <Type>
con Option Strict
:
Private misDoubles As Double() = {1.5, 2, 9.9, 18, 3.14}
Ejemplo: Array de objetos de clase
Dim arrFoo(5) As Foo
For i As Integer = 0 To arrFoo.Count - 1
arrFoo(i).Bar = i * 10 ' Excepción
Next
El array ha sido creado, pero los objetos de tipo Foo
en el no lo ha sido.
Solución
For i As Integer = 0 To arrFoo.Count - 1
arrFoo(i) = New Foo() ' Crear instancia de Foo
arrFoo(i).Bar = i * 10
Next
Usando una List(Of T)
hará que sea bastante difícil tener un elemento sin un objeto válido:
Dim FooList As New List(Of Foo) ' Lista creadad, pero está vacia
Dim f As Foo ' Variable temporal para el bucle
For i As Integer = 0 To 5
f = New Foo() ' Instancia de Foo creada
f.Bar = i * 10
FooList.Add(f) ' objeto de tipo Foo añadido a la lista
Next
Para mas información, ver:
Listas y Colecciones
Las colecciones en .NET (de las cuales hay muchas variedades - Listas, Diccionarios, etc.) también deben ser instanciadas o creadas.
Private miLista As List(Of String)
..
miLista.Add("prueba") ' NullReference
Obtienes la misma excepción por la misma razón - miLista
fue únicamente declarada, pero no se creó ninguna instancia. La solución es la misma:
miLista = New List(Of String)
' O crear la instancia al declararla:
Private miLista As New List(Of String)
Un error común es una clase que usa un tipo(Type
) de colección :
Public Class Foo
Private barList As List(Of Bar)
Friend Function BarCount As Integer
Return barList.Count
End Function
Friend Sub AddItem(newBar As Bar)
If barList.Contains(newBar) = False Then
barList.Add(newBar)
End If
End Function
Ambos procedimientos provocarán una NRE, porque barList
solo fue declarada, no instanciada. Crear una instancia de Foo
no creará también una instancia de la barList
interna. Puede que la intención fuera hacerlo en el constructor:
Public Sub New ' Constructor
' Cosas que hacer cuando se crea un nuevo Foo...
barList = New List(Of Bar)
End Sub
Igual que antes,esto no es correcto:
Public Sub New()
' Crea otra barList local a este procedimiento
Dim barList As New List(Of Bar)
End Sub
Para mas información, ver Clase List<T>
.
Objetos Proovedores de Datos
Trabajar con bases de datos hace que existan muchas oportunidades para una NullReferenceException ya que puede haber muchos objetos (Command
, Connection
, Transaction
, Dataset
, DataTable
, DataRows
....) en uso al mismo tiempo. Nota: Da igual que proovedor de datos utilices -- MySQL, SQL Server, OleDB, etc. -- los conceptos son los mismos.
Ejemplo 1
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows As Integer
con.Open()
Dim sql = "SELECT * FROM tblfoobar_List"
da = New OleDbDataAdapter(sql, con)
da.Fill(ds, "foobar")
con.Close()
MaxRows = ds.Tables("foobar").Rows.Count ' Error
Como antes, el Dataset ds
ha sido declarado, pero nunca se creó una instancia del mismo. El DataAdapter
llena un DataSet
que ya existe, no crea uno. En este caso, ya que ds
es una variable local, el IDE te lanza un aviso de que esto podría ocurrir:
Cuando es declarada como una variable a nivel de módulo/clase, como parece ser el caso con con
, el compilador no puede saber si el objeto fue creado por un procedimiento ascendente. No ignores las advertencias.
Solución
Dim ds As New DataSet
Ejemplo 2
ds = New DataSet
da = New OleDBDataAdapter(sql, con)
da.Fill(ds, "Empleados")
txtID.Text = ds.Tables("Empleado").Rows(0).Item(1)
txtID.Name = ds.Tables("Empleado").Rows(0).Item(2)
Un error tipográfico es el problema aquí: Empleados
-> Empleado
. No existe ningún DataTable
que se llame "Empleado", así que una NullReferenceException
resulta de intentar acceder a ella. Otro problema potencial es asumir que existirán Items
, lo cual puede no ser verdad cuando la consulta SQL contienen una cláusula WHERE.
Solución
Ya que solo se está usando una tabla en el ejemplo, usar Tables(0)
evitará errores de ortografía. Examinar Rows.Count
puede ayudar también:
If ds.Tables(0).Rows.Count > 0 Then
txtID.Text = ds.Tables(0).Rows(0).Item(1)
txtID.Name = ds.Tables(0).Rows(0).Item(2)
End If
Fill
es una función que devuelve el numero de filas(Rows
) afectadas que tambien puede ser comprobada:
If da.Fill(ds, "Empleados") > 0 Then...
Ejemplo 3
Dim da As New OleDb.OleDbDataAdapter("SELECT TICKET.TICKET_NO,
TICKET.CUSTOMER_ID, ... FROM TICKET_RESERVATION AS TICKET INNER JOIN
FLIGHT_DETAILS AS FLIGHT ... WHERE [TICKET.TICKET_NO]= ...", con)
Dim ds As New DataSet
da.Fill(ds)
If ds.Tables("TICKET_RESERVATION").Rows.Count > 0 Then
El DataAdapter
proporcionará TableNames
como se ve en el ejemplo anterior, pero no analiza los nombres de la tabla de la base de datos. A resultas de esto, ds.Tables("TICKET_RESERVATION")
referencia una tabla que no existe.
La solución es la misma, referencia la tabla por su indice:
If ds.Tables(0).Rows.Count > 0 Then
Ver también Clase DataTable.
Rutas de objetos(Object Paths) / Anidados(Nested)
If myFoo.Bar.Items IsNot Nothing Then
...
El código solo esta probando Items
mientras que myFoo
y Bar
también podrían ser Nothing
. La solución es probar la cadena entera o la tura del los objetos de uno en uno:
If (myFoo IsNot Nothing) AndAlso
(myFoo.Bar IsNot Nothing) AndAlso
(myFoo.Bar.Items IsNot Nothing) Then
....
AndAlso
es importante. Los tests subsecuentes no se ejecutarán una vez se encuentre la primera condición False
. Esto permite al código ir comprobando los objetos de nivel en nivel de forma segura, evaluando myFoo.Bar
solo después (y si) se determina que myFoo
es valido. Las cadenas o rutas de objetos pueden llegar a ser bastante largas cuando se trata con objetos complejos:
myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename")
Tampoco es posible referenciar nada por debajo de un objeto nulo. Esto se aplica también a los controles:
myWebBrowser.Document.GetElementById("formfld1").InnerText = "un valor"
Aquí, myWebBrowser
o Document
podrían ser Nothing
, o el elemento formfld1
podría no existir.
UI Controles
Dim cmd5 As New SqlCommand("select Cartons, Pieces, Foobar " _
& "FROM Invoice where invoice_no = '" & _
Me.ComboBox5.SelectedItem.ToString.Trim & "' And category = '" & _
Me.ListBox1.SelectedItem.ToString.Trim & "' And item_name = '" & _
Me.ComboBox2.SelectedValue.ToString.Trim & "' And expiry_date = '" & _
Me.expiry.Text & "'", con)
Entre otras cosas, este código no prevee que el usuario podría no haber seleccionado nada en uno o mas controles. ListBox1.SelectedItem
podría perfectamente ser Nothing
, así que ListBox1.SelectedItem.ToString
provocará una NRE.
Solución
Valida los datos antes de usarlos (es recomendable también usar Option Strict
y parámetros SQL):
Dim expiry As DateTime ' para validar un texto de una fecha If (ComboBox5.SelectedItems.Count > 0) AndAlso
(ListBox1.SelectedItems.Count > 0) AndAlso
(ComboBox2.SelectedItems.Count > 0) AndAlso
(DateTime.TryParse(expiry.Text, expiry) Then
'... hacer cosas
Else
MessageBox.Show(...mensaje de error...)
End If
De forma alternativa, podrías usar también (ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Formularios Visual Basic
Public Class Form1
Private NameBoxes = New TextBox(5) {Controls("TextBox1"), _
Controls("TextBox2"), Controls("TextBox3"), _
Controls("TextBox4"), Controls("TextBox5"), _
Controls("TextBox6")}
' lo mismo en un formato diferente:
Private boxList As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}
' NRE Inmediato:
Private unaVariable As String = Me.Controls("TextBox1").Text
Esta es una forma muy común de obtener una NRE. En C#, dependiendo de cómo
esté programado, el IDE reportaría que Controls
no existe en el contexto actual, o "No se puede tener acceso a un miembro no estático desde un ámbito estático". Así que, en cierto modo esta es una situación que sólo puede darse en VB. Es también una situación compleja, porque puede causar un fallo en cascada.
Los arrays y las colecciones no se pueden inicializar de esta manera. Este código de inicialización se ejecutará antes de que el constructor cree el Formulario o los controles(Controls
). Como resultado:
- Las Listas y Colecciones estarán simplemente vacías
- El Array contendrá cinco elementos de
Nothing
- La asignación a
unaVariable
resultará en una NRE inmediata, porque Nothing
no tiene una propiedad .Text
Referenciar los elementos del array mas tarde resultará en una NRE. Si lo haces en el Form_Load
, debido a un bug extraño, el IDE podría no reportar la excepción cuando ocurra. La excepción aparecerá mas tarde cuando tu código intent usar el array. Esta "excepción silenciosa" es detallada en este post (en inglés). Para nuestro propósito, la clave es que cuando algo catastrófico ocurre al crear un formulario (Sub New
o evento Form Load
), las excepciones podrían no reportarse. El flujo sale del procedimiento y simplemente muestra el formulario.
Dado que ningún código mas en tu Sub New
o en tu evento Form Load
se ejecutará después de la NRE, un montón de otras cosas podrían quedarse sin inicializar.
Sub Form_Load(..._
'...
Dim name As String = NameBoxes(2).Text ' NRE
' ...
' Mas código (que probablemente no se ejecutará)
' ...
End Sub
Nota esto aplica para cualquiera y todas las referencias a controles y componentes haciendo esto ilegal donde se encuentre:
Public Class Form1
Private myFiles() As String = Me.OpenFileDialog1.FileName & ...
Private dbcon As String = OpenFileDialog1.FileName & ";Jet Oledb..."
Private studentName As String = TextBox13.Text
Solución parcial
Es curioso que VB no de al menos un aviso, pero la solución es declarar los contenedores a nivel de formulario, pero inicializarles en el evento form load cuando los controles realmente existen. Esto se puede hacer también en Sub New
siempre y cuando tu código esté después de la llamada a InitializeComponent
:
' Declaración a nivel de módulo
Private NameBoxes as TextBox()
Private studentName As String
' Form Load, Form Shown or Sub New:
'
' (ilegal usando OPTION STRICT)
NameBoxes = New TextBox() {Me.Controls("TextBox1"), Me.Controls("TestBox2"), ...)
studentName = TextBox32.Text
El código del array podría no estar a salvo todavía. Cualquier control que esté en un control contenedor (como un GroupBox
o Panel
) no se encontrará en Me.Controls
; estarán en la colección Controls
de ese Panel o GroupBox. Tampoco se devolverá ningun control si su nombre está mal escrito ("TeStBox2"
). En esos casos, en esos elementos del array se almacenará Nothing
y resultará en una NRE cuando intentes referenciarlos.
Estos deberían ser fáciles de encontrar ahora que ya sabes lo que estás buscando:
"Button2" está contenido en un Panel
Solución
En lugar de usar referencias indirectas por nombre usando la colección Controls
del formulario, usa la referencia del control:
' Declaración
Private NameBoxes As TextBox()
' Inicializacion - simple y fácil de leer, difícil de "chapucear":
NameBoxes = New TextBox() {TextBox1, TextBox2, ...)
' Inicializar una lista
NamesList = New List(Of TextBox)({TextBox1, TextBox2, TextBox3...})
' o
NamesList = New List(Of TextBox)
NamesList.AddRange({TextBox1, TextBox2, TextBox3...})
Function que devuelve Nothing
Private bars As New List(Of Bars) ' Declarado y creado
Public Function BarList() As List(Of Bars)
bars.Clear
If someCondition Then
For n As Integer = 0 to someValue
bars.Add(GetBar(n))
Next n
Else
Exit Function
End If
Return bars
End Function
Este es un caso donde el IDE mostrará un aviso de que 'no todas las rutas devuelve un valor lo que puede resultar en una NullReferenceException
'. Puedes suprimir el aviso sustituyendo Exit Function
con Return Nothing
, pero eso no resuelve el problema. Cualquier cosa que intente usar el valor devuelto cuando someCondition = False
resultará en una NRE:
bList = myFoo.BarList()
For Each b As Bar in bList ' EXCEPCION
...
Solución
Cambia Exit Function
en la función por Return bList
. Devolver una lista(List
) vacía no es lo mismo que devolver Nothing
. Si existe la posibilidad de que un objeto devuelto pueda ser Nothing
, compruébalo antes de usarlo:
bList = myFoo.BarList()
If bList IsNot Nothing Then...
Try/Catch mal implementado
Un Try/Catch mal implementado puede ocultar donde está el problema y provocar como consecuencia otros nuevos:
Dim dr As SqlDataReader
Try
Dim lnk As LinkButton = TryCast(sender, LinkButton)
Dim gr As GridViewRow = DirectCast(lnk.NamingContainer, GridViewRow)
Dim eid As String = GridView1.DataKeys(gr.RowIndex).Value.ToString()
ViewState("username") = eid
sqlQry = "select FirstName, Surname, DepartmentName, ExtensionName, jobTitle,
Pager, mailaddress, from employees1 where username='" & eid & "'"
If connection.State <> ConnectionState.Open Then
connection.Open()
End If
command = New SqlCommand(sqlQry, connection)
'Mas código
dr = command.ExecuteReader()
If dr.Read() Then
lblFirstName.Text = Convert.ToString(dr("FirstName"))
...
End If
mpe.Show()
Catch
Finally
command.Dispose()
dr.Close() ' <-- NRE
connection.Close()
End Try
Este caso es el de un objeto que no ha sido creado como se esperaba, pero también demuestra la "extrema" utilidad de un Catch
vacío.
Hay una coma de más en el SQL (después de 'mailaddress') que causa una excepción en .ExecuteReader
. Después de que Catch
no haga nada, Finally
intenta hacer limpieza, pero como no puedes cerrar(Close
) un DataReader
nulo, una nueva NullReferenceException
es lanzada.
Un bloque Catch
vacío es muy peligroso y nada recomendable. Este OP estaba sorprendido intentando entender porqué estaba obteniendo una NRE en el bloque Finally
. En otras situaciones, un Catch
vacío podría resultar en algo mucho mas grave y hacerte perder mucho tiempo probando cosas equivocadas en el lugar equivocado para encontrar el problema. (La "excepción silenciosa" descrita anteriormente proporciona el mismo entretenimiento añadido.)
Solución
No uses bloques Try/Catch vacios - deja que el código falle para que puedas a) identificar la causa b) indetificar la localización y c) aplicar la solución correcta. Los bloques Try/Catch no se hicieron para ocultar las excepciones de la persona cualificada para solucionarlas - el desarrollador.
DBNull no es lo mismo que Nothing
For Each row As DataGridViewRow In dgvPlanning.Rows
If Not IsDBNull(row.Cells(0).Value) Then
...
La funciónIsDBNull
se usa para comprobar si un valor es igual que System.DBNull
: De MSDN:
El valor System.DBNull indica que el objeto representa datos que faltan o no existen. DBNull no es lo mismo que Nothing, que indica que una variable aun no ha sido inicializada.
Solución
If row.Cells(0) IsNot Nothing Then ...
Como antes, puedes comprobar primero Nothing
, y después por un valor específico:
If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then
Ejemplo 2
Dim getFoo = (From f In dbContext.FooBars
Where f.something = something
Select f).FirstOrDefault
If Not IsDBNull(getFoo) Then
If IsDBNull(getFoo.user_id) Then
txtFirst.Text = getFoo.first_name
Else
...
FirstOrDefault
devuelve el primer elemento o el valor por defecto, que en el caso de tipos de referencia es Nothing
y nunca DBNull
:
If getFoo IsNot Nothing Then...
Controles
Dim chk As CheckBox
chk = CType(Me.Controls(chkName), CheckBox)
If chk.Checked Then
Return chk
End If
Si un CheckBox
con chkName
no se encuentra (o existe en un GroupBox
), entonces chk
será Nothing
y el intento de referenciar cualquier propiedad resultará en una excepción.
Solución
If (chk IsNot Nothing) AndAlso (chk.Checked) Then ...
El DataGridView
El DGV tiene algunos "caprichos" que se ven periódicamente:
dgvBooks.DataSource = loan.Books
dgvBooks.Columns("ISBN").Visible = True ' NullReferenceException
dgvBooks.Columns("Title").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Author").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Price").DefaultCellStyle.Format = "C"
Si dgvBooks
tiene AutoGenerateColumns = True
, creará las columnas pero no las pondrá nombre, así que el código de arriba falla cuando trata de referenciarlas por nombre.
Solución
Pon nombre a las columnas manualmente, o referéncialas por índice:
dgvBooks.Columns(0).Visible = True
Ejemplo 2 — Cuidado con NewRow
xlWorkSheet = xlWorkBook.Sheets("sheet1")
For i = 0 To myDGV.RowCount - 1
For j = 0 To myDGV.ColumnCount - 1
For k As Integer = 1 To myDGV.Columns.Count
xlWorkSheet.Cells(1, k) = myDGV.Columns(k - 1).HeaderText
xlWorkSheet.Cells(i + 2, j + 1) = myDGV(j, i).Value.ToString()
Next
Next
Next
Cuando tu DataGridView
tiene AllowUserToAddRows
a True
(pro defecto), las Cells
en la fila vacía/nueva al final contendrán todas Nothing
. Los intentos de usar los contenidos de ésta (por ejemplo, ToString
) resultarán en una NRE.
Solución
Usa un bucle For/Each
y pregunta por la propiedad IsNewRow
para determinar si es la última fila. Esto funciona aunque AllowUserToAddRows
sea true o false:
For Each r As DataGridViewRow in myDGV.Rows
If r.IsNewRow = False Then
' puedes usar esta fila
Si usas un bucle For n
, modifica el contador de filas o usa Exit For
cuando IsNewRow
es true.
My.Settings (StringCollection)
Bajo ciertas circunstancias, intentado usar un elemento de My.Settings
que es un StringCollection
puede resultar en una NullReference la primera vez que lo usas. La solución es la misma, aunque no tan obvia. Considera:
My.Settings.FooBars.Add("ziggy") ' foobars es una string collection
Ya que VB está gestionando Settings por ti, es razonable esperar que inicialice la colección. Lo hará, pero solo si previamente has añadido un elemento inicial a la colección (en el editor de Settings). Ya que la colección esta siendo (aparentemente) inicializada cuando un elemento es añadido, permanece a Nothing
cuando no hay elementos en el editor de Settings para añadir.
Solución
Inicializa la colección de settings en el manejador del evento Load
del formulario, si es necesario:
If My.Settings.FooBars Is Nothing Then
My.Settings.FooBars = New System.Collections.Specialized.StringCollection
End If
Típicamente, la colección Settings
solo necesitaría ser inicializada la primera vez que se ejecute la aplicación. Una solución alternativa es añadir un valor inicial a la colección en Proyecto -> Settings | FooBars, guardar el proyecto y posteriormente eliminar el valor falso.
Puntos Clave
Probablemente olvidaste el operador New
.
o
Algo que asumías que funcionaría perfectamente para devolver un objeto inicializado, no lo ha hecho.
No ignores los avisos del compilador (nunca) y usa Option Strict On
(siempre).
MSDN Clase NullReferenceException
Esta respuesta es una traducción de esta respuesta de Stack Overflow