Caros futuros visitantes, as respostas a esta pergunta se aplicam igualmente a uma ArgumentNullException . Se sua pergunta foi encerrada como uma duplicata desta e você está enfrentando uma ANE, siga as instruções nas respostas para depurar e corrigir seu problema.
@ ANE só deve acontecer se um nulo for passado como parâmetro. Você pode dar um exemplo se uma pergunta da ANE for fechada como duplicata desta?
John Saunders
Ele apareceu no Meta, mas eu teria que procurar o link. Mas, quanto a esse comentário, um ANE é simplesmente um NRE, mas alguém adicionou uma verificação preventiva, e você pelo menos sabe exatamente o que é nulo (o nome do argumento é fornecido), por isso é um pouco mais fácil de diagnosticar do que um NRE direto.
Respostas:
2415
Qual é a causa?
Bottom Line
Você está tentando usar algo que é null(ou Nothingno VB.NET). Isso significa que você deve defini-lo como nullou nunca defini-lo como qualquer coisa.
Como qualquer outra coisa, nullé repassado. Se estiver nullno método "A", pode ser que o método "B" tenha passado a nullpara o método "A".
null pode ter significados diferentes:
Variáveis de objeto que não foram inicializadas e, portanto, não apontam para nada. Nesse caso, se você acessar propriedades ou métodos de tais objetos, isso causará a NullReferenceException.
O desenvolvedor está usando nullintencionalmente para indicar que não há valor significativo disponível. Observe que o C # tem o conceito de tipos de dados nulos para variáveis (como as tabelas do banco de dados podem ter campos nulos) - você pode atribuir nulla eles para indicar que não há valor armazenado nele, por exemplo, int? a = null;onde o ponto de interrogação indica que é permitido armazenar nulo em variável a. Você pode verificar isso com if (a.HasValue) {...}ou com if (a==null) {...}. Variáveis anuláveis, como aeste exemplo, permitem acessar o valor via a.Valueexplicitamente, ou apenas como via normal a. Observe que acessá-lo via a.Valuelança um em InvalidOperationExceptionvez de um NullReferenceExceptionse aénull- você deve fazer a verificação antecipadamente, ou seja, se você tiver outra variável anulável int b;, deverá fazer atribuições como if (a.HasValue) { b = a.Value; }ou mais curta if (a != null) { b = a; }.
O restante deste artigo entra em mais detalhes e mostra os erros que muitos programadores cometem, o que pode levar a um NullReferenceException.
Mais especificamente
O runtimejogando um NullReferenceExceptionsempre significa a mesma coisa: você está tentando usar uma referência, e a referência não é inicializado (ou foi uma vez inicializado, mas é não inicializado).
Isso significa que a referência é nulle você não pode acessar membros (como métodos) por meio de uma nullreferência. O caso mais simples:
string foo =null;
foo.ToUpper();
Isso lançará um NullReferenceExceptionna segunda linha porque você não pode chamar o método de instância ToUpper()em uma stringreferência apontando para null.
Depuração
Como você encontra a fonte de um NullReferenceException? Além de observar a exceção em si, que será lançada exatamente no local em que ocorre, as regras gerais de depuração no Visual Studio se aplicam: coloque pontos de interrupção estratégicos e inspecione suas variáveis , passando o mouse sobre seus nomes, abrindo um ( Rápido) Observe a janela ou use os vários painéis de depuração, como Locals e Autos.
Se você deseja descobrir onde a referência está ou não está definida, clique com o botão direito do mouse no nome e selecione "Localizar todas as referências". Você pode colocar um ponto de interrupção em todos os locais encontrados e executar seu programa com o depurador conectado. Sempre que o depurador interrompe esse ponto de interrupção, é necessário determinar se você espera que a referência seja nula, inspecione a variável e verifique se ela aponta para uma instância quando você espera.
Seguindo o fluxo do programa dessa maneira, é possível encontrar o local em que a instância não deve ser nula e por que ela não está definida corretamente.
Exemplos
Alguns cenários comuns em que a exceção pode ser lançada:
Genérico
ref1.ref2.ref3.member
Se ref1 ou ref2 ou ref3 for nulo, você receberá a NullReferenceException. Se você deseja resolver o problema, descubra qual deles é nulo reescrevendo a expressão para seu equivalente mais simples:
Especificamente, em HttpContext.Current.User.Identity.Name, HttpContext.Currentpoderia ser nulo ou a Userpropriedade poderia ser nula ou a Identitypropriedade poderia ser nula.
Indireto
publicclassPerson{publicintAge{get;set;}}publicclassBook{publicPersonAuthor{get;set;}}publicclassExample{publicvoidFoo(){Book b1 =newBook();int authorAge = b1.Author.Age;// You never initialized the Author property.// there is no Person to get an Age from.}}
Se você deseja evitar a referência nula filho (Pessoa), você pode inicializá-la no construtor do objeto pai (Livro).
Inicializadores de objetos aninhados
O mesmo se aplica aos inicializadores de objetos aninhados:
Book b1 =newBook{Author={Age=45}};
Isso se traduz em
Book b1 =newBook();
b1.Author.Age=45;
Enquanto a newpalavra-chave é usada, ela cria apenas uma nova instância de Book, mas não uma nova instância Person, portanto Authora propriedade permanece imóvel null.
A coleção aninhada Initializersse comporta da mesma maneira:
Person p1 =newPerson{Books={newBook{Title="Title1"},newBook{Title="Title2"},}};
Isso se traduz em
Person p1 =newPerson();
p1.Books.Add(newBook{Title="Title1"});
p1.Books.Add(newBook{Title="Title2"});
O new Personúnico cria uma instância de Person, mas a Bookscoleção ainda é null. A Initializersintaxe da coleção não cria uma coleção para p1.Books, ela se traduz apenas nas p1.Books.Add(...)instruções.
Matriz
int[] numbers =null;int n = numbers[0];// numbers is null. There is no array to index.
Elementos da matriz
Person[] people =newPerson[5];
people[0].Age=20// people[0] is null. The array was allocated but not// initialized. There is no Person to set the Age for.
Matrizes irregulares
long[][] array =newlong[1][];
array[0][0]=3;// is null because only the first dimension is yet initialized.// Use array[0] = new long[2]; first.
Coleção / Lista / Dicionário
Dictionary<string,int> agesForNames =null;int age = agesForNames["Bob"];// agesForNames is null.// There is no Dictionary to perform the lookup.
Variável de intervalo (indireto / diferido)
publicclassPerson{publicstringName{get;set;}}var people =newList<Person>();
people.Add(null);var names =from p in people select p.Name;string firstName = names.First();// Exception is thrown here, but actually occurs// on the line above. "p" is null because the// first element we added to the list is null.
Eventos
publicclassDemo{publiceventEventHandlerStateChanged;protectedvirtualvoidOnStateChanged(EventArgs e){StateChanged(this, e);// Exception is thrown here // if no event handlers have been attached// to StateChanged event}}###Bad Naming Conventions:If you named fields differently from locals, you might have realized that you never initialized the field.
Isso pode ser resolvido seguindo a convenção de prefixar campos com um sublinhado:
privateCustomer _customer;
Ciclo de vida da página ASP.NET:
publicpartialclassIssues_Edit:System.Web.UI.Page{protectedTestIssue myIssue;protectedvoidPage_Load(object sender,EventArgs e){if(!IsPostBack){// Only called on first load, not when button clicked
myIssue =newTestIssue();}}protectedvoidSaveButton_Click(object sender,EventArgs e){
myIssue.Entry="NullReferenceException here!";}}
Valores da sessão do ASP.NET
// if the "FirstName" session value has not yet been set,// then this line will throw a NullReferenceExceptionstring firstName =Session["FirstName"].ToString();
Modelos de exibição vazia do ASP.NET MVC
Se a exceção ocorrer ao fazer referência a uma propriedade de @Modelem um ASP.NET MVC View, você precisará entender que isso Modelé definido no seu método de ação, quando você returnvisualiza. Quando você retorna um modelo vazio (ou propriedade de modelo) do seu controlador, a exceção ocorre quando as visualizações o acessam:
// ControllerpublicclassRestaurant:Controller{publicActionResultSearch(){returnView();// Forgot the provide a Model here.}}// Razor view @foreach(var restaurantSearch inModel.RestaurantSearch)// Throws.{}<p>@Model.somePropertyName</p><!--Alsothrows-->
Ordem de criação de controle WPF e eventos
WPFOs controles são criados durante a chamada InitializeComponentna ordem em que aparecem na árvore visual. A NullReferenceExceptionserá gerado no caso de controles criados anteriormente com manipuladores de eventos etc., aquele disparo durante o InitializeComponentqual os controles criados tardiamente serão referenciados.
Por exemplo :
<Grid><!-- Combobox declared first --><ComboBoxName="comboBox1"Margin="10"SelectedIndex="0"SelectionChanged="comboBox1_SelectionChanged"><ComboBoxItemContent="Item 1"/><ComboBoxItemContent="Item 2"/><ComboBoxItemContent="Item 3"/></ComboBox><!-- Label declared later --><LabelName="label1"Content="Label"Margin="10"/></Grid>
Aqui comboBox1é criado antes label1. Se comboBox1_SelectionChangedtentar referenciar `label1, ele ainda não foi criado.
Alterar a ordem das declarações em XAML(ou seja, listar label1antes comboBox1, ignorando questões da filosofia do design, pelo menos resolveria o problema NullReferenceExceptionaqui).
Elenco com as
var myThing = someObject asThing;
Isso não InvalidCastExceptiongera um, mas retorna a nullquando o elenco falha (e quando someObjecté nulo). Então, fique ciente disso.
LINQ FirstOrDefault()eSingleOrDefault()
As versões simples First()e Single()lançam exceções quando não há nada. As versões "OrDefault" retornam nulo nesse caso. Então, fique ciente disso.
para cada
foreachlança quando você tenta iterar a coleção nula. Geralmente causado por nullresultado inesperado de métodos que retornam coleções.
List<int> list =null;foreach(var v in list){}// exception
Exemplo mais realista - selecione nós do documento XML. Será lançada se os nós não forem encontrados, mas a depuração inicial mostrar que todas as propriedades são válidas:
foreach(var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))
Verifique explicitamente nulle forneça um valor padrão.
Chamada de métodos que você espera que uma instância possa retornar null, por exemplo, quando o objeto que está sendo procurado não puder ser encontrado. Você pode optar por retornar um valor padrão quando este for o caso:
Verifique explicitamente as nullchamadas de método e crie uma exceção personalizada.
Você também pode lançar uma exceção personalizada, apenas para capturá-la no código de chamada:
stringGetCategory(string bookTitle){var book = library.FindBook(bookTitle);// This may return nullif(book ==null)thrownewBookNotFoundException(bookTitle);// Your custom exceptionreturn book.Category;}
Use Debug.Assertse um valor nunca deve ser null, para capturar o problema mais cedo do que a exceção ocorre.
Quando você sabe durante o desenvolvimento que um método pode, mas nunca deve retornar null, você pode usar Debug.Assert()para interromper o mais rápido possível quando ocorrer:
stringGetTitle(int knownBookID){// You know this should never return null.var book = library.GetBook(knownBookID);// Exception will occur on the next line instead of at the end of this method.Debug.Assert(book !=null,"Library didn't return a book for known book ID.");// Some other codereturn book.Title;// Will never throw NullReferenceException in Debug mode.}
Embora essa verificação não termine na construção da versão , fazendo com que seja lançadaNullReferenceException novamente quando estiver book == nullem tempo de execução no modo de liberação.
Use GetValueOrDefault()para nullabletipos de valor para fornecer um valor padrão quando estiverem null.
DateTime? appointment =null;Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));// Will display the default value provided (DateTime.Now), because appointment is null.
appointment =newDateTime(2022,10,20);Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));// Will display the appointment date, not the default
Use o operador coalescente nulo: ??[C #] ou If()[VB].
A abreviação para fornecer um valor padrão quando a nullé encontrado:
IServiceCreateService(ILogger log,Int32? frobPowerLevel){var serviceImpl =newMyService(log ??NullLog.Instance);// Note that the above "GetValueOrDefault()" can also be rewritten to use// the coalesce operator:
serviceImpl.FrobPowerLevel= frobPowerLevel ??5;}
Use o operador de condição nula: ?.ou ?[x]para matrizes (disponíveis em C # 6 e VB.NET 14):
Às vezes, isso também é chamado de operador de navegação segura ou Elvis (após seu formato). Se a expressão no lado esquerdo do operador for nula, o lado direito não será avaliado e o nulo será retornado. Isso significa casos como este:
var title = person.Title.ToUpper();
Se a pessoa não tiver um título, isso gerará uma exceção porque está tentando chamar ToUpperuma propriedade com um valor nulo.
Dentro C# 5e abaixo, isso pode ser protegido com:
var title = person.Title==null?null: person.Title.ToUpper();
Agora, a variável title será nula em vez de lançar uma exceção. O C # 6 apresenta uma sintaxe mais curta para isso:
var title = person.Title?.ToUpper();
Isso resultará na variável title null, e a chamada para ToUppernão será feita, se person.Titlefor null.
Obviamente, você ainda precisa verificar se titlehá nulo ou usar o operador de condição nula junto com o operador de coalescência nula ( ??) para fornecer um valor padrão:
// regular null checkint titleLength =0;if(title !=null)
titleLength = title.Length;// If title is null, this would throw NullReferenceException// combining the `?` and the `??` operatorint titleLength = title?.Length??0;
Da mesma forma, para matrizes, você pode usar da ?[i]seguinte maneira:
Isso fará o seguinte: Se myIntArrayfor nulo, a expressão retornará nulo e você poderá verificá-la com segurança. Se ele contiver uma matriz, fará o mesmo que:
elem = myIntArray[i];e retorna o i<sup>th</sup>elemento.
Use o contexto nulo (disponível em C # 8):
Introduzido nos C# 8contextos nulos e nos tipos de referência anuláveis, executam análises estáticas nas variáveis e fornecem um aviso do compilador se um valor puder ser potencialmente nulo ou tiver sido definido como nulo. Os tipos de referência anuláveis permitem explicitamente que os tipos sejam nulos.
O contexto de anotação anulável e o contexto de aviso anulável podem ser definidos para um projeto usando o Nullableelemento no seu csprojarquivo. Este elemento configura como o compilador interpreta a nulidade dos tipos e quais avisos são gerados. As configurações válidas são:
enable: O contexto de anotação anulável está ativado. O contexto de aviso anulável está ativado. Variáveis de um tipo de referência, sequência por exemplo, não são anuláveis. Todos os avisos de nulidade estão ativados.
desativar: O contexto de anotação anulável está desativado. O contexto de aviso anulável está desativado. Variáveis de um tipo de referência são inconscientes, assim como as versões anteriores do C #. Todos os avisos de nulidade estão desativados.
safeonly: o contexto de anotação anulável está ativado. O contexto de aviso anulável é seguro. Variáveis de um tipo de referência não são anuláveis. Todos os avisos de nulidade de segurança estão ativados.
avisos: O contexto de anotação anulável está desativado. O contexto de aviso anulável está ativado. Variáveis de um tipo de referência são inconscientes. Todos os avisos de nulidade estão ativados.
safeonlywarnings: o contexto de anotação anulável está desativado. O contexto de aviso anulável é seguro. Variáveis de um tipo de referência são inconscientes. Todos os avisos de nulidade de segurança estão ativados.
Um tipo de referência anulável é observado usando a mesma sintaxe que os tipos de valor anulável: a ?é anexado ao tipo da variável.
Técnicas especiais para depuração e correção de derefs nulos em iteradores
C#suporta "blocos iteradores" (chamados "geradores" em outros idiomas populares). Exceções de dereferência nula podem ser particularmente difíceis de depurar em blocos de iteradores devido à execução adiada:
publicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}...FrobFactory factory = whatever;IEnumerable<Frobs> frobs =GetFrobs();...foreach(Frob frob in frobs){...}
Se whateveros resultados em nullseguida, MakeFrobvai jogar. Agora, você pode pensar que a coisa certa a fazer é:
// DON'T DO THISpublicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){if(f ==null)thrownewArgumentNullException("f","factory must not be null");for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}
Por que isso está errado? Como o bloco iterador não é executado até o foreach! A chamada para GetFrobssimplesmente retorna um objeto que, quando iterado , executará o bloco iterador.
Ao escrever uma verificação nula como essa, você evita a desreferência nula, mas move a exceção de argumento nulo para o ponto da iteração , não para o ponto da chamada , e isso é muito confuso para depuração .
A correção correta é:
// DO THISpublicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){// No yields in a public method that throws!if(f ==null)thrownewArgumentNullException("f","factory must not be null");returnGetFrobsForReal(f, count);}privateIEnumerable<Frob>GetFrobsForReal(FrobFactory f,int count){// Yields in a private methodDebug.Assert(f !=null);for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}
Ou seja, crie um método auxiliar privado que tenha a lógica de bloco do iterador e um método de superfície pública que faça a verificação nula e retorne o iterador. Agora, quando GetFrobsé chamada, a verificação nula acontece imediatamente e é GetFrobsForRealexecutada quando a sequência é iterada.
Se você examinar a fonte de referência para LINQObjetos, verá que essa técnica é usada por toda parte. É um pouco mais complicado de escrever, mas facilita muito a depuração de erros de nulidade. Otimize seu código para a conveniência do chamador, não para o autor .
Uma observação sobre dereferences nulos em código não seguro
C#possui um modo "inseguro", que, como o nome indica, é extremamente perigoso, porque os mecanismos de segurança normais que fornecem segurança de memória e segurança de tipo não são aplicados. Você não deve escrever código inseguro, a menos que tenha um entendimento profundo e profundo de como a memória funciona .
No modo não seguro, você deve estar ciente de dois fatos importantes:
desreferenciar um ponteiro nulo produz a mesma exceção que desreferenciar uma referência nula
desreferenciar um ponteiro não nulo inválido pode produzir essa exceção em algumas circunstâncias
Para entender por que isso acontece, é útil entender como o .NET produz exceções de desreferência nula em primeiro lugar. (Esses detalhes se aplicam ao .NET em execução no Windows; outros sistemas operacionais usam mecanismos semelhantes.)
A memória é virtualizada Windows; cada processo obtém um espaço de memória virtual de muitas "páginas" de memória que são rastreadas pelo sistema operacional. Cada página da memória possui sinalizadores definidos que determinam como ela pode ser usada: leitura, gravação, execução etc. A página mais baixa é marcada como "produza um erro, se alguma vez for usada de alguma maneira".
Um ponteiro nulo e uma referência nula C#são representados internamente como o número zero e, portanto, qualquer tentativa de desreferencia-lo em seu armazenamento de memória correspondente faz com que o sistema operacional produza um erro. O tempo de execução do .NET detecta esse erro e o transforma na exceção de desreferência nula.
É por isso que desreferenciar um ponteiro nulo e uma referência nula produz a mesma exceção.
E o segundo ponto? Anular a referência a qualquer ponteiro inválido que caia na página mais baixa da memória virtual causa o mesmo erro do sistema operacional e, portanto, a mesma exceção.
Por que isso faz sentido? Bem, suponha que tenhamos uma estrutura contendo duas entradas e um ponteiro não gerenciado igual a nulo. Se tentarmos desreferenciar o segundo int na estrutura, CLRele não tentará acessar o armazenamento no local zero; ele acessará o armazenamento no local quatro. Mas, logicamente, essa é uma dereferência nula, porque estamos chegando a esse endereço via nula.
Se você estiver trabalhando com código não seguro e receber uma exceção de desreferência nula, lembre-se de que o ponteiro incorreto não precisa ser nulo. Pode ser qualquer local na página mais baixa e essa exceção será produzida.
Talvez esse seja um comentário idiota, mas a primeira e melhor maneira de evitar esse problema seria inicializar o objeto? Para mim, se esse erro ocorre, geralmente é porque esqueci de inicializar algo como o elemento da matriz. Eu acho que é muito menos comum definir o objeto como nulo e depois fazer referência a ele. Talvez seja o caminho para resolver cada problema adjacente à descrição. Ainda é um bom post.
JPK
30
E se não houver objeto, mas o valor de retorno de um método ou propriedade?
John Saunders
6
O exemplo do livro / autor é um pouco estranho ... Como isso é compilado? Como o intellisense funciona? O que é isso, eu não sou bom com computar ...
5
@ Will: minha última edição ajuda? Caso contrário, seja mais explícito sobre o que você vê como um problema.
John Saunders
6
@ JohnSaunders Oh, não, desculpe, eu quis dizer a versão inicializadora de objetos disso. new Book { Author = { Age = 45 } };Como é que a inicialização interna ainda ... Não consigo pensar em uma situação em que o init interno funcionaria, mas compila e o intellisense funciona ... A menos que por estruturas?
311
Exceção NullReference - Visual Basic
O NullReference Exceptionpara Visual Basic não é diferente daquele em c # . Afinal, ambos estão relatando a mesma exceção definida no .NET Framework que ambos usam. Causas exclusivas do Visual Basic são raras (talvez apenas uma).
Esta resposta usará termos, sintaxe e contexto do Visual Basic. Os exemplos usados vêm de um grande número de perguntas anteriores do Stack Overflow. Isso é para maximizar a relevância usando os tipos de situações geralmente vistas nas postagens. Um pouco mais de explicação também é fornecida para aqueles que precisam. Um exemplo semelhante ao seu é muito provável aqui.
Nota:
Isso é baseado em conceito: não há código para você colar no seu projeto. Destina-se a ajudá-lo a entender o que causa um NullReferenceException(NRE), como encontrá-lo, como corrigi-lo e como evitá-lo. Um NRE pode ser causado de várias maneiras, por isso é improvável que seja seu único encontro.
Os exemplos (das postagens Stack Overflow) nem sempre mostram a melhor maneira de fazer algo em primeiro lugar.
Normalmente, o remédio mais simples é usado.
Significado básico
A mensagem "Objeto não definido para uma instância de Objeto" significa que você está tentando usar um objeto que não foi inicializado. Isso se resume a um destes:
Seu código declarou uma variável de objeto, mas não a inicializou (crie uma instância ou ' instancie ')
Algo que seu código assumiu inicializaria um objeto, não
Possivelmente, outro código invalidou prematuramente um objeto ainda em uso
Encontrando a causa
Como o problema é uma referência a objeto Nothing, a resposta é examiná-lo para descobrir qual. Em seguida, determine por que não foi inicializado. Mantenha o mouse sobre as várias variáveis e o Visual Studio (VS) mostrará seus valores - o culpado será Nothing.
Você também deve remover todos os blocos Try / Catch do código relevante, especialmente aqueles onde não há nada no bloco Catch. Isso fará com que seu código falhe ao tentar usar um objeto que é Nothing. É isso que você deseja, porque identificará o local exato do problema e permitirá identificar o objeto que está causando o problema.
A MsgBoxna captura que exibe Error while...será de pouca ajuda. Esse método também leva a questões muito ruins de Stack Overflow, porque você não pode descrever a exceção real, o objeto envolvido ou mesmo a linha de código onde ela ocorre.
Você também pode usar o Locals Window( Debug -> Windows -> Locals ) para examinar seus objetos.
Depois de saber qual e onde está o problema, geralmente é bastante fácil de corrigir e mais rápido do que postar uma nova pergunta.
Dim reg As CashRegister
...
TextBox1.Text = reg.Amount ' NRE
O problema é que Dimnão cria um objeto CashRegister ; apenas declara uma variável denominada regdesse tipo. Declarar uma variável de objeto e criar uma instância são duas coisas diferentes.
Remédio
O Newoperador geralmente pode ser usado para criar a instância quando você a declara:
Dim reg AsNew CashRegister ' [New] creates instance, invokes the constructor' Longer, more explicit form:Dim reg As CashRegister =New CashRegister
Quando é apropriado apenas criar a instância posteriormente:
Nota: Não use Dimnovamente em um procedimento, incluindo o construtor ( Sub New):
Private reg As CashRegister
'...PublicSubNew()'...Dim reg AsNew CashRegister
EndSub
Isso criará uma variável localreg , que existe apenas nesse contexto (sub). A regvariável com o nível do módulo Scopeque você usará em qualquer outro lugar permanece Nothing.
A falta do Newoperador é a principal causa de problemasNullReference Exceptions nas perguntas de estouro de pilha revisadas.
O Visual Basic tenta tornar o processo claro repetidamente usando New: Usar o NewOperador cria um novo objeto e chama Sub New- o construtor - onde seu objeto pode executar qualquer outra inicialização.
Para ser claro, Dim(ou Private) declara apenas uma variável e sua Type. O escopo da variável - se existe para todo o módulo / classe ou é local para um procedimento - é determinado pelo local em que é declarado. Private | Friend | Publicdefine o nível de acesso, não o escopo .
Essa matriz foi declarada apenas, não criada. Existem várias maneiras de inicializar uma matriz:
Private arr asString()=NewString(10){}' orPrivate arr()AsString=NewString(10){}' For a local array (in a procedure) and using 'Option Infer':Dim arr =NewString(10){}
Nota: A partir do VS 2010, ao inicializar uma matriz local usando um literal e Option Infer, os elementos As <Type>e Newsão opcionais:
Dim myDbl AsDouble()={1.5,2,9.9,18,3.14}Dim myDbl =NewDouble(){1.5,2,9.9,18,3.14}Dim myDbl()={1.5,2,9.9,18,3.14}
O tipo de dados e o tamanho da matriz são inferidos a partir dos dados que estão sendo atribuídos. Declarações nível de classe / Módulo ainda requerem As <Type>com Option Strict:
Private myDoubles AsDouble()={1.5,2,9.9,18,3.14}
Exemplo: Matriz de Objetos de Classe
Dim arrFoo(5)As Foo
For i AsInteger=0To arrFoo.Count -1
arrFoo(i).Bar = i *10' ExceptionNext
A matriz foi criada, mas os Fooobjetos nela não.
Remédio
For i AsInteger=0To arrFoo.Count -1
arrFoo(i)=New Foo()' Create Foo instance
arrFoo(i).Bar = i *10Next
Usar um List(Of T)tornará bastante difícil ter um elemento sem um objeto válido:
Dim FooList AsNew List(Of Foo)' List created, but it is emptyDim f As Foo ' Temporary variable for the loopFor i AsInteger=0To5
f =New Foo()' Foo instance created
f.Bar = i *10
FooList.Add(f)' Foo object added to listNext
As coleções do .NET (das quais existem muitas variedades - listas, dicionário etc.) também devem ser instanciadas ou criadas.
Private myList As List(Of String)..
myList.Add("ziggy")' NullReference
Você obtém a mesma exceção pelo mesmo motivo - myListfoi declarado apenas, mas nenhuma instância foi criada. O remédio é o mesmo:
myList =New List(Of String)' Or create an instance when declared:Private myList AsNew List(Of String)
Uma supervisão comum é uma classe que usa uma coleção Type:
PublicClass Foo
Private barList As List(Of Bar)FriendFunction BarCount AsIntegerReturn barList.Count
EndFunctionFriendSub AddItem(newBar As Bar)If barList.Contains(newBar)=FalseThen
barList.Add(newBar)EndIfEndFunction
Qualquer procedimento resultará em um NRE, porque barListé declarado apenas, não instanciado. Criar uma instância de Footambém não criará uma instância do interno barList. Pode ter sido a intenção de fazer isso no construtor:
PublicSubNew' Constructor' Stuff to do when a new Foo is created...
barList =New List(Of Bar)EndSub
Como antes, isso está incorreto:
PublicSubNew()' Creates another barList local to this procedureDim barList AsNew List(Of Bar)EndSub
Trabalhando com bancos de dados apresenta muitas oportunidades para um NullReference porque pode haver muitos objetos ( Command, Connection, Transaction, Dataset, DataTable, DataRows....) em uso ao mesmo tempo. Nota: Não importa qual provedor de dados você está usando - MySQL, SQL Server, OleDB etc. - os conceitos são os mesmos.
Exemplo 1
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows AsInteger
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, o dsobjeto Conjunto de dados foi declarado, mas uma instância nunca foi criada. O DataAdapterirá preencher um existente DataSet, não criar um. Nesse caso, como dsé uma variável local, o IDE avisa que isso pode acontecer:
Quando declarado como uma variável de nível de módulo / classe, como parece ser o caso con, o compilador não pode saber se o objeto foi criado por um procedimento upstream. Não ignore avisos.
Um erro de digitação é um problema aqui: Employeesvs Employee. Não havia um DataTablenome "Funcionário" criado; portanto, um NullReferenceExceptionresultado está tentando acessá-lo. Outro problema em potencial é supor que haverá o Itemsque pode não ser assim quando o SQL incluir uma cláusula WHERE.
Remédio
Como isso usa uma tabela, a utilização Tables(0)evitará erros de ortografia. O exame Rows.Counttambém pode ajudar:
If ds.Tables(0).Rows.Count >0Then
txtID.Text = ds.Tables(0).Rows(0).Item(1)
txtID.Name = ds.Tables(0).Rows(0).Item(2)EndIf
Fillé uma função retornando o número de Rowsafetados que também pode ser testado:
If da.Fill(ds,"Employees")>0Then...
Exemplo 3
Dim da AsNew 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 AsNew DataSet
da.Fill(ds)If ds.Tables("TICKET_RESERVATION").Rows.Count >0Then
Ele DataAdapterserá fornecido TableNamescomo mostrado no exemplo anterior, mas não analisa nomes da tabela SQL ou do banco de dados. Como resultado, faz ds.Tables("TICKET_RESERVATION")referência a uma tabela inexistente.
O remédio é o mesmo, faça referência à tabela por índice:
O código está testando apenas Itemsenquanto ambos myFooe Bartambém pode ser Nothing. O remédio é testar toda a cadeia ou caminho dos objetos, um de cada vez:
AndAlsoé importante. Os testes subsequentes não serão executados quando a primeira Falsecondição for encontrada. Isso permite que o código 'perfure' com segurança no (s) objeto (s), um 'nível' de cada vez, avaliando myFoo.Barsomente depois que (e se) myFoofor determinado como válido. Cadeias ou caminhos de objetos podem ficar muito longos ao codificar objetos complexos:
Aqui, myWebBrowserou Documentpoderia ser Nothing ou o formfld1elemento pode não existir.
Controles da interface do usuário
Dim cmd5 AsNew 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 outras coisas, esse código não prevê que o usuário possa não ter selecionado algo em um ou mais controles da interface do usuário. ListBox1.SelectedItempode muito bem ser Nothing, então ListBox1.SelectedItem.ToStringresultará em um NRE.
Remédio
Valide os dados antes de usá-los (também use Option Stricte parâmetros SQL):
Dim expiry As DateTime ' for text date validationIf(ComboBox5.SelectedItems.Count >0)AndAlso(ListBox1.SelectedItems.Count >0)AndAlso(ComboBox2.SelectedItems.Count >0)AndAlso(DateTime.TryParse(expiry.Text, expiry)Then'... do stuffElse
MessageBox.Show(...error message...)EndIf
Como alternativa, você pode usar (ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Formulários do Visual Basic
PublicClass Form1
Private NameBoxes =New TextBox(5){Controls("TextBox1"), _
Controls("TextBox2"), Controls("TextBox3"), _
Controls("TextBox4"), Controls("TextBox5"), _
Controls("TextBox6")}' same thing in a different format:Private boxList AsNew List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}' Immediate NRE:Private somevar AsString=Me.Controls("TextBox1").Text
Essa é uma maneira bastante comum de obter um NRE. Em C #, dependendo de como é codificado, o IDE relatará que Controlsnão existe no contexto atual ou "não pode fazer referência a membro não estático". Então, até certo ponto, essa é uma situação apenas de VB. Também é complexo porque pode resultar em uma cascata de falha.
As matrizes e coleções não podem ser inicializadas dessa maneira. Esse código de inicialização será executado antes que o construtor crie o Formou o Controls. Como um resultado:
Listas e coleções simplesmente ficarão vazias
A matriz conterá cinco elementos de Nothing
A somevaratribuição resultará em uma NRE imediata porque Nothing não possui uma .Textpropriedade
A referência a elementos da matriz posteriormente resultará em um NRE. Se você fizer isso Form_Load, devido a um erro estranho, o IDE poderá não relatar a exceção quando isso acontecer. A exceção será exibida mais tarde quando seu código tentar usar a matriz. Essa "exceção silenciosa" é detalhada nesta postagem . Para nossos propósitos, a chave é que, quando algo catastrófico acontece ao criar um formulário ( Sub Newou Form Loadevento), as exceções podem não ser relatadas, o código sai do procedimento e apenas exibe o formulário.
Como nenhum outro código no seu evento Sub Newou Form Loadserá executado após o NRE, muitas outras coisas podem ser deixadas não inicializadas.
Sub Form_Load(..._
'...Dim name AsString= NameBoxes(2).Text ' NRE' ...' More code (which will likely not be executed)' ...EndSub
Observe que isso se aplica a toda e qualquer referência de controle e componente, tornando-as ilegais onde estão:
É curioso que VB não fornecer um aviso, mas o remédio é declarar os recipientes ao nível do formulário, mas inicializar -los em manipulador de eventos load forma quando os controles fazer existir. Isso pode ser feito Sub Newdesde que seu código seja após a InitializeComponentchamada:
' Module level declarationPrivate NameBoxes as TextBox()Private studentName AsString' Form Load, Form Shown or Sub New:'' Using the OP's approach (illegal using OPTION STRICT)
NameBoxes =New TextBox(){Me.Controls("TextBox1"),Me.Controls("TestBox2"),...)
studentName = TextBox32.Text ' For simple control references
O código do array ainda pode não estar fora de perigo. Quaisquer controles que estejam em um controle de contêiner (como um GroupBoxou Panel) não serão encontrados Me.Controls; eles estarão na coleção Controls desse Panel ou GroupBox. Um controle também não será retornado quando o nome do controle estiver incorreto ( "TeStBox2"). Nesses casos, Nothingserá novamente armazenado nesses elementos da matriz e um NRE resultará quando você tentar fazer referência a ele.
Isso deve ser fácil de encontrar agora que você sabe o que está procurando:
"Button2" reside em um Panel
Remédio
Em vez de referências indiretas por nome usando a Controlscoleção do formulário , use a referência de controle:
' DeclarationPrivate NameBoxes As TextBox()' Initialization - simple and easy to read, hard to botch:
NameBoxes =New TextBox(){TextBox1, TextBox2,...)' Initialize a List
NamesList =New List(Of TextBox)({TextBox1, TextBox2, TextBox3...})' or
NamesList =New List(Of TextBox)
NamesList.AddRange({TextBox1, TextBox2, TextBox3...})
Função Retornando Nada
Private bars AsNew List(Of Bars)' Declared and createdPublicFunction BarList()As List(Of Bars)
bars.Clear
If someCondition ThenFor n AsInteger=0to someValue
bars.Add(GetBar(n))Next n
ElseExitFunctionEndIfReturn bars
EndFunction
É um caso em que o IDE avisa que ' nem todos os caminhos retornam um valor e NullReferenceExceptionpodem resultar '. Você pode suprimir o aviso, substituindo Exit Functionpor Return Nothing, mas isso não resolve o problema. Qualquer coisa que tentar usar o retorno quando someCondition = Falseresultará em um NRE:
bList = myFoo.BarList()ForEach b As Bar in bList ' EXCEPTION...
Remédio
Substitua Exit Functionna função por Return bList. Retornar um vazioList não é o mesmo que retornar Nothing. Se houver uma chance de um objeto retornado Nothing, teste antes de usá-lo:
Um Try / Catch mal implementado pode ocultar onde está o problema e resultar em novos:
Dim dr As SqlDataReader
TryDim lnk As LinkButton = TryCast(sender, LinkButton)Dim gr As GridViewRow =DirectCast(lnk.NamingContainer, GridViewRow)Dim eid AsString= 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()EndIf
command =New SqlCommand(sqlQry, connection)'More code fooing and barring
dr = command.ExecuteReader()If dr.Read()Then
lblFirstName.Text = Convert.ToString(dr("FirstName"))...EndIf
mpe.Show()CatchFinally
command.Dispose()
dr.Close()' <-- NRE
connection.Close()EndTry
Este é o caso de um objeto que não está sendo criado conforme o esperado, mas também demonstra a contra-utilidade de um vazio Catch.
Há uma vírgula extra no SQL (após 'endereço de email') que resulta em uma exceção em .ExecuteReader. Após o Catchnão fazer nada, Finallytenta executar a limpeza, mas como você não pode Closeum DataReaderobjeto nulo , NullReferenceExceptionresulta em um novo resultado.
Um Catchbloco vazio é o playground do diabo. Este OP ficou confuso por que ele estava recebendo um NRE no Finallybloco. Em outras situações, um vazio Catchpode resultar em algo muito mais a jusante e fazer com que você gaste tempo olhando as coisas erradas no lugar errado para o problema. (A "exceção silenciosa" descrita acima fornece o mesmo valor de entretenimento.)
Remédio
Não use blocos Try / Catch vazios - deixe o código travar para que você possa: a) identificar a causa b) identificar o local ec) aplicar um remédio adequado. Os blocos Try / Catch não têm como objetivo ocultar exceções da pessoa qualificada exclusivamente para corrigi-los - o desenvolvedor.
DBNull não é o mesmo que Nothing
ForEach row As DataGridViewRow In dgvPlanning.Rows
IfNot IsDBNull(row.Cells(0).Value)Then...
A IsDBNullfunção é usada para testar se um valor é igual a System.DBNull: No MSDN:
O valor System.DBNull indica que o objeto representa dados ausentes ou inexistentes. DBNull não é o mesmo que Nothing, o que indica que uma variável ainda não foi inicializada.
Remédio
If row.Cells(0) IsNot NothingThen...
Como antes, você pode testar o Nothing e, em seguida, obter um valor específico:
Dim getFoo =(From f In dbContext.FooBars
Where f.something = something
Select f).FirstOrDefault
IfNot IsDBNull(getFoo)ThenIf IsDBNull(getFoo.user_id)Then
txtFirst.Text = getFoo.first_name
Else...
FirstOrDefaultretorna o primeiro item ou o valor padrão, que é Nothingpara tipos de referência e nunca DBNull:
If getFoo IsNot NothingThen...
Controles
Dim chk As CheckBox
chk =CType(Me.Controls(chkName), CheckBox)If chk.Checked ThenReturn chk
EndIf
Se um CheckBoxcom chkNamenão puder ser encontrado (ou existir em a GroupBox), chkserá Nothing e tentar fazer referência a qualquer propriedade resultará em uma exceção.
Remédio
If(chk IsNot Nothing)AndAlso(chk.Checked)Then...
O DataGridView
A DGV tem algumas peculiaridades vistas periodicamente:
Se dgvBookstiver AutoGenerateColumns = True, ele criará as colunas, mas não as nomeará; portanto, o código acima falhará quando as referenciar por nome.
Remédio
Nomeie as colunas manualmente ou faça referência por índice:
Quando você DataGridViewtiver AllowUserToAddRowscomo True(o padrão), o campo Cellsem branco / nova linha na parte inferior conterá todos Nothing. A maioria das tentativas de usar o conteúdo (por exemplo ToString) resultará em um NRE.
Remédio
Use um For/Eachloop e teste a IsNewRowpropriedade para determinar se é a última linha. Isso funciona se AllowUserToAddRowsé verdadeiro ou não:
ForEach r As DataGridViewRow in myDGV.Rows
If r.IsNewRow =FalseThen' ok to use this row
Se você usar um For nloop, modifique a contagem de linhas ou use Exit Forquando IsNewRowfor verdadeiro.
My.Settings (StringCollection)
Sob certas circunstâncias, tentar usar um item do My.Settingsqual é um StringCollectionpode resultar em um NullReference na primeira vez que você o usa. A solução é a mesma, mas não tão óbvia. Considerar:
My.Settings.FooBars.Add("ziggy")' foobars is a string collection
Como o VB está gerenciando as configurações para você, é razoável esperar que ele inicialize a coleção. Será, mas somente se você tiver adicionado anteriormente uma entrada inicial à coleção (no editor de Configurações). Como a coleção é (aparentemente) inicializada quando um item é adicionado, ela permanece Nothingquando não há itens no editor de Configurações a serem adicionados.
Remédio
Inicialize a coleção de configurações no Loadmanipulador de eventos do formulário , se / quando necessário:
If My.Settings.FooBars IsNothingThen
My.Settings.FooBars =New System.Collections.Specialized.StringCollection
EndIf
Normalmente, a Settingscoleção só precisa ser inicializada na primeira vez que o aplicativo é executado. Uma solução alternativa é adicionar um valor inicial à sua coleção em Projeto -> Configurações | FooBars , salve o projeto e remova o valor falso.
Pontos chave
Você provavelmente esqueceu o Newoperador.
ou
Algo que você assumiu que executaria perfeitamente para retornar um objeto inicializado ao seu código, não o fez.
Não ignore os avisos do compilador (sempre) e use Option Strict On(sempre).
Outro cenário é quando você lança um objeto nulo em um tipo de valor . Por exemplo, o código abaixo:
object o =null;DateTime d =(DateTime)o;
Ele jogará um NullReferenceExceptionno elenco. Parece bastante óbvio no exemplo acima, mas isso pode acontecer em cenários intrincados de "ligação tardia", em que o objeto nulo foi retornado de algum código que você não possui e a conversão é, por exemplo, gerada por algum sistema automático.
Um exemplo disso é este fragmento de ligação simples do ASP.NET com o controle Calendar:
Aqui, de SelectedDatefato , é uma propriedade - do DateTimetipo - do tipo CalendarWeb Control, e a ligação pode retornar perfeitamente algo nulo. O gerador implícito do ASP.NET criará um código que será equivalente ao código de conversão acima. E isso irá gerar um NullReferenceExceptionque é bastante difícil de detectar, porque está no código gerado pelo ASP.NET que compila bem ...
Isso lançará o erro porque, embora eu tenha declarado a variável " connection", ela não está apontada para nada. Quando tento ligar para o membro " Open", não há referência para sua resolução e isso gerará o erro.
Para evitar esse erro:
Sempre inicialize seus objetos antes de tentar fazer algo com eles.
Se você não tiver certeza se o objeto é nulo, verifique com object == null.
A ferramenta Resharper do JetBrains identificará todos os locais em seu código que têm a possibilidade de um erro de referência nulo, permitindo que você faça uma verificação nula. Este erro é a fonte número um de bugs, IMHO.
A ferramenta Resharper do JetBrains identificará todos os locais em seu código que têm a possibilidade de um erro de referência nulo. Isto está incorreto. Eu tenho uma solução sem essa detecção, mas o código ocasionalmente resulta na exceção. Eu suspeito que às vezes seja indetectável - pelo menos por eles - quando o multithreading está envolvido, mas não posso comentar mais porque ainda não identifiquei a localização do meu bug.
j riv
Mas como resolvê-lo quando a NullReferenceException entrar em uso HttpContext.Current.Responce.Clear (). Não está sendo resolvido por nenhuma das soluções acima. porque ao criar seu objeto objeto de HttpContext, surge um erro "A resolução da sobrecarga falhou porque nenhum 'Novo' acessível aceita esse número de argumentos.
Sunny Sandeep
158
Isso significa que seu código usou uma variável de referência de objeto que foi definida como nula (ou seja, não fez referência a uma instância de objeto real).
Para evitar o erro, os objetos que poderiam ser nulos devem ser testados quanto a nulos antes de serem utilizados.
if(myvar !=null){// Go ahead and use myvar
myvar.property=...}else{// Whoops! myvar is null and cannot be used without first// assigning it to an instance reference// Attempting to use myvar here will result in NullReferenceException}
Esteja ciente de que, independentemente do cenário, a causa é sempre a mesma no .NET:
Você está tentando usar uma variável de referência cujo valor é Nothing/ null. Quando o valor é Nothing/ nullpara a variável de referência, isso significa que na verdade não está mantendo uma referência a uma instância de qualquer objeto que exista na pilha.
Você nunca atribuiu algo à variável, nunca criou uma instância do valor atribuído à variável, ou configurou a variável igual a Nothing/ nullmanualmente ou chamou uma função que definiu a variável para Nothing/ nullpara você.
Um exemplo dessa exceção sendo lançada é: Quando você está tentando verificar algo, isso é nulo.
Por exemplo:
string testString =null;//Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)if(testString.Length==0)// Throws a nullreferenceexception{//Do something}
O tempo de execução do .NET lançará uma NullReferenceException quando você tentar executar uma ação em algo que não foi instanciado, ou seja, o código acima.
Em comparação com um ArgumentNullException que normalmente é lançado como uma medida defensiva se um método espera que o que está sendo passado para ele não seja nulo.
O C # 8.0 apresenta tipos de referência nulos e tipos de referência não nulos . Portanto, apenas tipos de referência anuláveis devem ser verificados para evitar uma NullReferenceException .
Se você não inicializou um tipo de referência e deseja definir ou ler uma de suas propriedades, ele lançará uma NullReferenceException .
Exemplo:
Person p =null;
p.Name="Harry";// NullReferenceException occurs here.
Você pode simplesmente evitar isso verificando se a variável não é nula:
Person p =null;if(p!=null){
p.Name="Harry";// Not going to run to this point}
Para entender completamente por que uma NullReferenceException é lançada, é importante saber a diferença entre tipos de valor e [tipos de referência] [3].
Portanto, se você estiver lidando com tipos de valor , NullReferenceExceptions não poderá ocorrer. Embora você precise manter-se alerta ao lidar com tipos de referência !
Somente tipos de referência, como o nome está sugerindo, podem conter referências ou apontar literalmente para nada (ou 'nulo'). Enquanto os tipos de valor sempre contêm um valor.
Tipos de referência (estes devem ser verificados):
dinâmico
objeto
corda
Tipos de valor (você pode simplesmente ignorar estes):
-1: como a pergunta é "O que é uma NullReferenceException", os tipos de valor não são relevantes.
John Saunders
21
@ John Saunders: Eu discordo. Como desenvolvedor de software, é realmente importante ser capaz de distinguir entre tipos de valor e referência. caso contrário, as pessoas acabarão verificando se números inteiros são nulos.
Fabian Bigler
5
É verdade, mas não no contexto desta questão.
John Saunders
4
Obrigado pela dica. Melhorei um pouco e adicionei um exemplo no topo. Eu ainda acho que mencionar tipos de referência e valor é útil.
Fabian Bigler
5
Acho que você não adicionou nada que não estivesse nas outras respostas, pois a pergunta supõe um tipo de referência.
John Saunders
78
Outro caso em NullReferenceExceptionsque isso pode acontecer é o uso (incorreto) do asoperador :
Aqui Booke Carsão tipos incompatíveis; a Carnão pode ser convertido / convertido em a Book. Quando esse elenco falha, asretorna null. O uso mybookapós isso causa a NullReferenceException.
Em geral, você deve usar um elenco ou as, da seguinte maneira:
Se você espera que a conversão de tipo seja sempre bem-sucedida (ou seja, você sabe o que o objeto deve estar adiantado), use uma conversão:
ComicBook cb =(ComicBook)specificBook;
Se você não tiver certeza do tipo, mas deseja tentar usá-lo como um tipo específico, use as:
Isso pode acontecer muito ao desembalar uma variável. Acho que isso acontece com frequência nos manipuladores de eventos depois de alterar o tipo do elemento da interface do usuário, mas esqueça de atualizar o code-behind.
Brendan
65
Você está usando o objeto que contém a referência de valor nulo. Portanto, está dando uma exceção nula. No exemplo, o valor da sequência é nulo e, ao verificar seu comprimento, ocorreu a exceção.
Exemplo:
stringvalue=null;if(value.Length==0)// <-- Causes exception{Console.WriteLine(value);// <-- Never reached}
O erro de exceção é:
Exceção não tratada:
System.NullReferenceException: referência de objeto não definida para uma instância de um objeto. em Program.Main ()
Quão profundo! Eu nunca considerei a constante 'nula' um valor de referência. Então é assim que o C # abstrai um "NullPointer" hein? Por mais que eu lembre-se em C ++, um NPE pode ser causado por desreferenciar um ponteiro não inicializado (ou seja, tipo ref em c #) cujo valor padrão é um endereço que não está alocado para esse processo (em muitos casos, 0, especialmente nas versões posteriores do C ++ que inicializaram automaticamente, que pertencem ao sistema operacional - f com ele e morrem de bip (ou apenas pegue o sigkill com o qual o sistema operacional ataca seu processo)).
samis 31/07
64
Enquanto o que causa um NullReferenceExceptions e abordagens para evitar / corrigir essa exceção foi abordado em outras respostas, o que muitos programadores ainda não aprenderam é como depurar independentemente essas exceções durante o desenvolvimento.
Agora, quando a NullReferenceException for lançada (ou não tratada), o depurador irá parar (lembra-se da regra definida acima?) Na linha em que ocorreu a exceção. Às vezes, o erro será fácil de detectar.
Por exemplo, na linha a seguir, o único código que pode causar a exceção é se o valor for myStringavaliado como nulo. Isso pode ser verificado olhando para a Janela de inspeção ou executando expressões na Janela imediata .
var x = myString.Trim();
Em casos mais avançados, como o seguinte, você precisará usar uma das técnicas acima (Monitorar ou Windows Imediato) para inspecionar as expressões e determinar se str1foi nulo ou se str2foi nulo.
var x = str1.Trim()+ str2.Trim();
Depois que a exceção é lançada, geralmente é trivial raciocinar para trás para descobrir onde o valor nulo foi [incorretamente] introduzido -
Aproveite o tempo necessário para entender a causa da exceção. Inspecione expressões nulas. Inspecione as expressões anteriores que poderiam ter resultado em tais expressões nulas. Adicione pontos de interrupção e siga o programa conforme apropriado. Use o depurador.
1 Se a interrupção na execução for muito agressiva e o depurador parar em um NPE na biblioteca .NET ou de terceiros, a interrupção na não tratada pelo usuário poderá ser usada para limitar as exceções capturadas. Além disso, o VS2012 apresenta Just My Code, que eu recomendo ativar também.
Se você estiver depurando com o Just My Code ativado, o comportamento será um pouco diferente. Com o Just My Code ativado, o depurador ignora as exceções do CLR (Common Language Runtime) de primeira chance que são lançadas fora do My Code e não passam pelo My Code
object o =null;DateTime d =(DateTime)o;// NullReferenceException
onde uma conversão de unboxing (conversão) deobject (ou de uma das classes System.ValueTypeou System.Enum, ou de um tipo de interface) para um tipo de valor (diferente de Nullable<>) em si fornece NullReferenceException.
Na outra direção, uma conversão de boxe de um Nullable<>que é HasValueigual falsea um tipo de referência pode fornecer uma nullreferência que pode posteriormente levar a a NullReferenceException. O exemplo clássico é:
DateTime? d =null;var s = d.ToString();// OK, no exception (no boxing), returns ""var t = d.GetType();// Bang! d is boxed, NullReferenceException
Às vezes o boxe acontece de outra maneira. Por exemplo, com este método de extensão não genérico:
Adicionando um caso em que o nome da classe da entidade usada na estrutura da entidade é o mesmo da classe de um arquivo code-behind do formulário da web.
Suponha que você tenha um formulário da Web Contact.aspx cuja classe por trás do código seja Contato e você tenha um nome de entidade Contato.
O código a seguir lançará uma NullReferenceException quando você chamar context.SaveChanges ()
Contact contact =newContact{Name="Abhinav"};var context =newDataContext();
context.Contacts.Add(contact);
context.SaveChanges();// NullReferenceException at this line
Por uma questão de completude da classe DataContext
O erro ocorre quando a entidade e a classe code-behind estão no mesmo espaço para nome. Para corrigir isso, renomeie a classe da entidade ou a classe code-behind para Contact.aspx.
Razão
Ainda não tenho certeza sobre o motivo. Mas sempre que qualquer classe de entidade estender o System.Web.UI.Page, esse erro ocorre.
Outro caso geral em que alguém pode receber essa exceção envolve zombar de classes durante o teste de unidade. Independentemente da estrutura de simulação usada, você deve garantir que todos os níveis apropriados da hierarquia de classes sejam simulados corretamente. Em particular, todas as propriedades HttpContextmencionadas pelo código em teste devem ser ridicularizadas.
Eu tenho uma perspectiva diferente para responder a isso. Esse tipo de resposta "o que mais posso fazer para evitá-lo? "
Ao trabalhar em diferentes camadas , por exemplo, em um aplicativo MVC, um controlador precisa de serviços para chamar operações de negócios. Nesses cenários, o Contêiner de injeção de dependência pode ser usado para inicializar os serviços para evitar a NullReferenceException . Isso significa que você não precisa se preocupar em procurar nulos e apenas chamar os serviços do controlador, como se eles sempre estivessem disponíveis (e inicializados) como um singleton ou um protótipo.
publicclassMyController{privateServiceA serviceA;privateServiceB serviceB;publicMyController(ServiceA serviceA,ServiceB serviceB){this.serviceA = serviceA;this.serviceB = serviceB;}publicvoidMyMethod(){// We don't need to check null because the dependency injection container // injects it, provided you took care of bootstrapping it.var someObject = serviceA.DoThis();}}
-1: trata apenas de um cenário único - o de dependências não inicializadas. Este é um cenário minoritário para NullReferenceException. A maioria dos casos é um mal-entendido simples de como os objetos funcionam. A seguir, as mais frequentes são outras situações em que o desenvolvedor assumiu que o objeto seria inicializado automaticamente.
John Saunders
Geralmente, a injeção de dependência não é usada para evitar NullReferenceException. Não acredito que você tenha encontrado um cenário geral aqui. De qualquer forma, se você editar sua resposta para ter mais estilo no estilo stackoverflow.com/a/15232518/76337 , removerei o voto negativo.
John Saunders
38
Sobre o assunto "o que devo fazer sobre isso" , pode haver muitas respostas.
Uma maneira mais "formal" de impedir essas condições de erro durante o desenvolvimento é aplicar o design por contrato no seu código. Isso significa que você precisa definir invariantes de classe e / ou até pré - condições e pós - condições de função / método em seu sistema durante o desenvolvimento.
Em resumo, os invariantes de classe garantem que haverá algumas restrições em sua classe que não serão violadas no uso normal (e, portanto, a classe não entrará em um estado inconsistente). As pré-condições significam que os dados fornecidos como entrada para uma função / método devem seguir algumas restrições definidas e nunca violá-las, e as pós - condições significam que uma saída da função / método deve seguir as restrições definidas novamente sem nunca violá-las. As condições do contrato nunca devem ser violadas durante a execução de um programa livre de erros; portanto, o design por contrato é verificado na prática no modo de depuração, enquanto está desabilitado nas versões , para maximizar o desempenho do sistema desenvolvido.
Dessa forma, você pode evitar NullReferenceExceptioncasos resultantes da violação das restrições definidas. Por exemplo, se você usar uma propriedade de objeto Xem uma classe e depois tentar chamar um de seus métodos e Xtiver um valor nulo, isso levará a NullReferenceException:
public X {get;set;}publicvoidInvokeX(){
X.DoSomething();// if X value is null, you will get a NullReferenceException}
Mas se você definir "a propriedade X nunca deve ter um valor nulo" como condição prévia do método, poderá impedir o cenário descrito anteriormente:
//Using code contracts:[ContractInvariantMethod]protectedvoidObjectInvariant(){Contract.Invariant( X !=null);//...}
Por essa causa, o projeto Code Contracts existe para aplicativos .NET.
Como alternativa, o design por contrato pode ser aplicado usando asserções .
Pensei em acrescentar isso porque ninguém mencionou isso e, na medida em que existe como uma abordagem, minha intenção era enriquecer o tópico.
Nick Louloudakis
2
Obrigado por enriquecer o tópico. Eu dei minha opinião sobre sua adição. Agora outros podem fazer o mesmo.
John Saunders
2
Eu pensei que isso era uma adição interessante ao tópico, uma vez que este é um tópico muito visto. Já ouvi falar de contratos de código antes e este foi um bom lembrete para considerar usá-los.
precisa saber é o seguinte
36
A NullReferenceExceptioné lançada quando estamos tentando acessar as propriedades de um objeto nulo ou quando um valor de string fica vazio e estamos tentando acessar métodos de string.
Por exemplo:
Quando um método de string de uma string vazia é acessado:
Isto está incorreto. String.Empty.ToLower()não lançará uma exceção de referência nula. Representa uma string real, embora uma vazia (ie ""). Como isso tem um objeto para chamar ToLower(), não faria sentido lançar uma exceção de referência nula lá.
Kjartan
31
TL; DR: tente usar em Html.Partialvez deRenderpage
Eu estava começando Object reference not set to an instance of an objectquando tentei renderizar uma View dentro de uma View enviando um Model, assim:
@{MyEntity M =newMyEntity();}@RenderPage("_MyOtherView.cshtml", M);// error in _MyOtherView, the Model was Null
A depuração mostrou que o modelo era Nulo no MyOtherView. Até que eu mudei para:
@{MyEntity M =newMyEntity();}@Html.Partial("_MyOtherView.cshtml", M);
E funcionou.
Além disso, o motivo pelo qual não precisei Html.Partialcomeçar foi porque o Visual Studio às vezes lança linhas onduladas com aparência de erro embaixo Html.Partialse estiver dentro de um foreachloop de construção diferente , mesmo que não seja realmente um erro:
@inheritsSystem.Web.Mvc.WebViewPage@{ViewBag.Title="Entity Index";List<MyEntity>MyEntities=newList<MyEntity>();MyEntities.Add(newMyEntity());MyEntities.Add(newMyEntity());MyEntities.Add(newMyEntity());}<div>@{foreach(var M inMyEntities){// Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?@Html.Partial("MyOtherView.cshtml");}}</div>
Mas consegui executar o aplicativo sem problemas com esse "erro". Consegui me livrar do erro alterando a estrutura do foreachloop para ficar assim:
@foreach(var M inMyEntities){...}
Embora eu tenha a sensação de que foi porque o Visual Studio estava interpretando mal os e comercial e os colchetes.
Além disso, mostre qual linha lançou a exceção e por quê.
31415 John Saunders
O erro ocorreu no MyOtherView.cshtml, que eu não incluí aqui, porque o modelo não estava sendo enviado corretamente (era Null), então eu sabia que o erro estava em como eu estava enviando o modelo.
Travis Heeter
22
O que você pode fazer sobre isso?
Há muitas boas respostas aqui explicando o que é uma referência nula e como depurá-la. Mas há muito pouco sobre como evitar o problema ou, pelo menos, facilitar a captura.
Verificar argumentos
Por exemplo, os métodos podem verificar os diferentes argumentos para ver se são nulos e lançar ArgumentNullExceptionuma exceção obviamente criada para esse propósito exato.
O construtor para o ArgumentNullExceptioneven leva o nome do parâmetro e uma mensagem como argumentos para que você possa dizer ao desenvolvedor exatamente qual é o problema.
publicvoidDoSomething(MyObject obj){if(obj ==null){thrownewArgumentNullException("obj","Need a reference to obj.");}}
Use ferramentas
Existem também várias bibliotecas que podem ajudar. "Resharper", por exemplo, pode fornecer avisos enquanto você escreve um código, especialmente se você usar o atributo: NotNullAttribute
Existem "Contratos de código da Microsoft", nos quais você usa sintaxe como a Contract.Requires(obj != null)que fornece verificação de tempo de execução e compilação: Introdução aos contratos de código .
Há também "PostSharp", que permitirá que você use apenas atributos como este:
publicvoidDoSometing([NotNull] obj)
Ao fazer isso e fazer do PostSharp parte do seu processo de compilação, objserá verificado se há nulo no tempo de execução. Consulte: Verificação nula PostSharp
Solução de código simples
Ou você pode sempre codificar sua própria abordagem usando código antigo simples. Por exemplo, aqui está uma estrutura que você pode usar para capturar referências nulas. Foi modelado com o mesmo conceito de Nullable<T>:
[System.Diagnostics.DebuggerNonUserCode]publicstructNotNull<T>where T:class{private T _value;public T Value{get{if(_value ==null){thrownewException("null value not allowed");}return _value;}set{if(value==null){thrownewException("null value not allowed.");}
_value =value;}}publicstaticimplicitoperator T(NotNull<T> notNullValue){return notNullValue.Value;}publicstaticimplicitoperatorNotNull<T>(T value){returnnewNotNull<T>{Value=value};}}
Você usaria muito semelhante da mesma maneira que usaria Nullable<T>, exceto com o objetivo de realizar exatamente o oposto - para não permitir null. aqui estão alguns exemplos:
NotNull<Person> person =null;// throws exceptionNotNull<Person> person =newPerson();// OKNotNull<Person> person =GetPerson();// throws exception if GetPerson() returns null
NotNull<T>é convertido implicitamente para e Tpara que você possa usá-lo em qualquer lugar que precisar. Por exemplo, você pode passar um Personobjeto para um método que leva umNotNull<Person> :
Person person =newPerson{Name="John"};WriteName(person);publicstaticvoidWriteName(NotNull<Person> person){Console.WriteLine(person.Value.Name);}
Como você pode ver acima, como no caso anulável, você acessaria o valor subjacente por meio da Valuepropriedade Como alternativa, você pode usar uma conversão explícita ou implícita; pode ver um exemplo com o valor de retorno abaixo:
Person person =GetPerson();publicstaticNotNull<Person>GetPerson(){returnnewPerson{Name="John"};}
Ou você pode até usá-lo quando o método retornar T(nesse caso Person) fazendo uma conversão. Por exemplo, o código a seguir gostaria apenas do código acima:
Person person =(NotNull<Person>)GetPerson();publicstaticPersonGetPerson(){returnnewPerson{Name="John"};}
Combinar com extensão
Combine NotNull<T>com um método de extensão e você pode cobrir ainda mais situações. Aqui está um exemplo de como o método de extensão pode ser:
[System.Diagnostics.DebuggerNonUserCode]publicstaticclassNotNullExtension{publicstatic T NotNull<T>(this T @this)where T:class{if(@this==null){thrownewException("null value not allowed");}return@this;}}
E aqui está um exemplo de como ele pode ser usado:
var person =GetPerson().NotNull();
GitHub
Para sua referência, disponibilizei o código acima no GitHub, você pode encontrá-lo em:
O C # 6.0 introduziu o "operador condicional nulo" que ajuda um pouco com isso. Com esse recurso, você pode fazer referência a objetos aninhados e, se algum deles for, nulltoda a expressão retornaránull .
Isso reduz o número de verificações nulas que você precisa fazer em alguns casos. A sintaxe é colocar um ponto de interrogação antes de cada ponto. Pegue o seguinte código, por exemplo:
var address = country?.State?.County?.City;
Imagine que esse countryé um objeto do tipo Countryque possui uma propriedade chamada Statee assim por diante. Se country, State, County, ou Cityé nullentão address will benulo . Therefore you only have to check whetherendereço isnull`.
É um ótimo recurso, mas fornece menos informações. Não torna óbvio qual dos quatro é nulo.
Incorporado como Anulável?
C # tem uma abreviação legal para Nullable<T>, você pode criar algo anulável colocando um ponto de interrogação após o tipoint? .
Seria bom se C # tinha algo parecido com a NotNull<T>estrutura acima e teve um atalho semelhante, talvez o ponto de exclamação para que você poderia escrever algo como (!): public void WriteName(Person! person).
@JohnSaunders ousa perguntar por quê? (Seriamente embora por quê?)
Luis Perez
2
NullReferenceException deve ser lançado pelo CLR. Isso significa que uma referência a um nulo ocorreu. Isso não significa que uma referência a um nulo ocorra, exceto que você foi habilmente verificado primeiro.
John Saunders
Entendo sua opinião sobre como isso seria confuso. Eu atualizei para uma exceção regular para este exemplo e uma exceção personalizada no GitHub.
Luis Perez
Ótima resposta para uma pergunta tão básica. Não é tão ruim quando seu código está falhando. É horrível quando está vindo de dentro de uma biblioteca comercial de terceiros em que você confia, e o suporte ao cliente continua insistindo que deve ser o seu código que está causando o problema. E você não tem certeza absoluta de que não é e todo o projeto é interrompido. Na verdade, acho que isso pode ser um epitáfio apropriado para minha lápide: "Referência de objeto não definida para uma instância de um objeto".
Darrel Lee 03/03
10
Curiosamente, nenhuma das respostas nesta página menciona os dois casos extremos, espero que ninguém se importe se eu os adicionar:
Caso 1 do Edge: acesso simultâneo a um dicionário
Dicionários genéricos no .NET não são seguros para threads e, às vezes, podem gerar um NullReferenceou até (mais frequente) umKeyNotFoundException quando você tenta acessar uma chave de dois threads simultâneos. A exceção é bastante enganosa neste caso.
Caso 2 do Edge: código não seguro
Se a NullReferenceExceptioné lançada pelo unsafecódigo, você pode examinar suas variáveis de ponteiro e verificar se háIntPtr.Zero ou algo assim. O que é a mesma coisa ("exceção de ponteiro nulo"), mas em código inseguro, as variáveis são frequentemente convertidas em tipos / matrizes de valor, etc., e você bate a cabeça na parede, imaginando como um tipo de valor pode gerar isso. exceção.
(Outro motivo para não usar código inseguro, a menos que você precise, a propósito)
O exemplo do seu dicionário não é um caso de ponta. Se o objeto não for seguro para threads, usá-lo em vários threads produz resultados aleatórios. Seu exemplo de código inseguro difere de nullque maneira?
John Saunders
10
Você pode corrigir NullReferenceException de maneira limpa usando Operadores com condição nula no c # 6 e escrever menos código para manipular verificações nulas.
É usado para testar nulos antes de executar uma operação de acesso de membro (?.) Ou índice (? [).
Exemplo
var name = p?.Spouse?.FirstName;
é equivalente a:
if(p !=null){if(p.Spouse!=null){
name = p.Spouse.FirstName;}}
O resultado é que o nome será nulo quando p for nulo ou quando p.Spouse for nulo.
Caso contrário, o nome da variável receberá o valor de p.Spouse.FirstName.
A linha de erro "Referência de objeto não definida para uma instância de um objeto." Afirma que você não atribuiu um objeto de instância a uma referência de objeto e ainda assim está acessando as propriedades / métodos desse objeto.
por exemplo: digamos que você tenha uma classe chamada myClass e ela contenha uma propriedade prop1.
publicClass myClass
{publicint prop1 {get;set;}}
Agora você está acessando este prop1 em alguma outra classe, como abaixo:
publicclassDemo{publicvoid testMethod(){
myClass ref=null;ref.prop1 =1;//This line throws error}}
a linha acima gera erro porque a referência da classe myClass é declarada, mas não instanciada, ou uma instância do objeto não é atribuída à referência dessa classe.
Para corrigir isso, é necessário instanciar (atribuir objeto à referência dessa classe).
A referência NullReferenceException ou Object não definida para uma instância de um objeto ocorre quando um objeto da classe que você está tentando usar não é instanciado. Por exemplo:
Como visto no código acima, a instrução
Student s - declara apenas a variável do tipo Student, observe que a classe Student não é instanciada neste momento. Portanto, quando a instrução s.GetFullName () for executada, ela lançará a NullReferenceException.
Você está tentando acessar um objeto que não foi criado ou atualmente não está na memória.
Então, como lidar com isso:
Depure e deixe o depurador quebrar ... Ele levará você diretamente para a variável que está quebrada ... Agora sua tarefa é simplesmente corrigir isso. Usando a nova palavra-chave no local apropriado.
Se isso é causado em alguns comandos do banco de dados porque o objeto não está presente, tudo o que você precisa fazer é fazer uma verificação nula e tratá-lo:
if(i ==null){// Handle this}
O mais difícil .. se o GC já coletou o objeto ... Isso geralmente ocorre se você estiver tentando encontrar um objeto usando cadeias ... Ou seja, localizando-o pelo nome do objeto, pode ser que o GC já esteja limpo ... Isso é difícil de encontrar e se tornará um problema ... Uma maneira melhor de resolver isso é fazer verificações nulas sempre que necessário durante o processo de desenvolvimento. Isso economizará muito tempo.
Ao encontrar pelo nome, quero dizer que alguma estrutura permite que você FIndObjects use seqüências de caracteres e o código fique assim: FindObject ("ObjectName");
Se você tem uma referência a um objeto, o GC nunca o limpa
John Saunders
2
se você usar coisas como FindObject ("Nome do objeto"), não há como a GC saber de antemão que você vai referenciar esse objeto .. é isso que estava tentando explicar .. isso ocorre em tempo de execução
Akash Gutha
2
Existem algumas estruturas que fornecem essa funcionalidade no C #, como o Unity. a questão não tem nada relacionado ao BCl. Pesquise na Internet antes de Criticar, existem inúmeras funções como elas e, para obter informações úteis, eu mesmo as uso diariamente. Agora, por favor, diga-me como a resposta não faz nenhum sentido.
Os exemplos que vi no seu link atribuem os resultados do GameObject.Find a um campo de membro. Essa é uma referência e o GC não a coletará até que o objeto que contém seja coletado.
John Saunders
1
Literalmente, a maneira mais fácil de corrigir uma NullReferenceExeption tem duas maneiras. Se você tiver um GameObject, por exemplo, com um script anexado e uma variável chamada rb (rigidbody), essa variável começará nula quando você iniciar o jogo.
É por isso que você obtém um NullReferenceExeption porque o computador não possui dados armazenados nessa variável.
Vou usar uma variável RigidBody como exemplo.
Podemos adicionar dados com muita facilidade, de várias maneiras:
Adicione um RigidBody ao seu objeto com AddComponent> Physics> Rigidbody.
Em seguida, entre no seu script e digite rb = GetComponent<Rigidbody>();
Esta linha de código funciona melhor nas suas funções Start()ou Awake().
Você pode adicionar um componente programaticamente e atribuir a variável ao mesmo tempo com uma linha de código: rb = AddComponent<RigidBody>();
Notas adicionais: Se você deseja que a unidade adicione um componente ao seu objeto e pode ter esquecido de adicioná-lo, digite [RequireComponent(typeof(RigidBody))]acima da sua declaração de classe (o espaço abaixo de todos os seus usos).
Aproveite e divirta-se fazendo jogos!
Isso é basicamente uma exceção de referência nula . Como a Microsoft declara
Uma exceção NullReferenceException é lançada quando você tenta acessar um membro de um tipo cujo valor é nulo.
O que isso significa?
Isso significa que, se algum membro que não possui nenhum valor e nós o obrigarmos a executar determinada tarefa, o sistema sem dúvida lançará uma mensagem e dirá:
"Ei, espere, esse membro não tem valores, portanto não pode executar a tarefa que você está entregando."
A própria exceção diz que algo está sendo referido, mas cujo valor não está sendo definido. Portanto, isso indica que isso ocorre apenas ao usar tipos de referência, pois os tipos Value não podem ser nulos.
NullReferenceException não ocorrerá se estivermos usando membros do tipo Valor.
O código acima mostra uma sequência simples que é atribuída com um valor nulo .
Agora, quando tento imprimir o comprimento da string str , recebo uma mensagem sem exceção do tipo 'System.NullReferenceException', porque o membro str está apontando para nulo e não pode haver nenhum tamanho nulo.
' NullReferenceException ' também ocorre quando esquecemos de instanciar um tipo de referência.
Suponha que eu tenha um método de classe e membro. Não instanciei minha classe, mas apenas nomeiei minha classe. Agora, se eu tentar usar o método, o compilador lançará um erro ou emitirá um aviso (dependendo do compilador).
classProgram{staticvoidMain(string[] args){MyClass1 obj;
obj.foo();//Use of unassigned local variable 'obj'}}publicclassMyClass1{internalvoid foo(){Console.WriteLine("hello from foo");}}
O compilador para o código acima gera um erro de que a variável obj não está atribuída, o que significa que nossa variável tem valores nulos ou nada. O compilador para o código acima gera um erro de que a variável obj não está atribuída, o que significa que nossa variável tem valores nulos ou nada.
Por que isso ocorre?
NullReferenceException surge devido a nossa falha por não verificar o valor do objeto. Geralmente, deixamos os valores do objeto desmarcados no desenvolvimento do código.
Também surge quando esquecemos de instanciar nossos objetos. O uso de métodos, propriedades, coleções etc. que podem retornar ou definir valores nulos também pode ser a causa dessa exceção.
Como isso pode ser evitado?
Existem várias maneiras e métodos para evitar essa renomada exceção:
Verificação explícita: Devemos seguir a tradição de verificar os objetos, propriedades, métodos, matrizes e coleções, sejam eles nulos. Isso pode ser simplesmente implementado usando instruções condicionais como if-else se-else etc.
Tratamento de exceções: uma das maneiras importantes de gerenciar essa exceção. Usando blocos simples try-catch-finalmente, podemos controlar essa exceção e também manter um log dela. Isso pode ser muito útil quando seu aplicativo estiver no estágio de produção.
Operadores nulos: O operador nulo de coalescência e os operadores condicionais nulos também podem ser úteis ao definir valores para objetos, variáveis, propriedades e campos.
Depurador: Para os desenvolvedores, temos a grande arma de depuração conosco. Se enfrentamos NullReferenceException durante o desenvolvimento, podemos usar o depurador para chegar à fonte da exceção.
Método interno: métodos do sistema, como GetValueOrDefault (), IsNullOrWhiteSpace () e IsNullorEmpty (), procuram nulos e atribuem o valor padrão se houver um valor nulo.
Já existem muitas boas respostas aqui. Você também pode verificar uma descrição mais detalhada com exemplos no meu blog .
Você basicamente copiou metade dessa postagem no blog e não adicionou nada novo que as respostas existentes não abordam.
CodeCaster
@ codecaster Diz-se copiar quando você reescreve um resumo do seu próprio blog. Sei que não há nada de novo na minha resposta e nada de novo que as respostas anteriores não tenham, mas desejo contribuir de maneira mais sofisticada e deixar que os outros entendam da maneira que eu entendi. Ficará feliz, mesmo que ajude uma única pessoa. Em boa fé.
Wasim
-4
Se alguém receber esta mensagem durante o salvamento ou compilação da compilação, feche todos os arquivos e abra qualquer arquivo para compilar e salvar.
Para mim, o motivo foi que eu havia renomeado o arquivo e o arquivo antigo ainda estava aberto.
Respostas:
Qual é a causa?
Bottom Line
Você está tentando usar algo que é
null
(ouNothing
no VB.NET). Isso significa que você deve defini-lo comonull
ou nunca defini-lo como qualquer coisa.Como qualquer outra coisa,
null
é repassado. Se estivernull
no método "A", pode ser que o método "B" tenha passado anull
para o método "A".null
pode ter significados diferentes:NullReferenceException
.null
intencionalmente para indicar que não há valor significativo disponível. Observe que o C # tem o conceito de tipos de dados nulos para variáveis (como as tabelas do banco de dados podem ter campos nulos) - você pode atribuirnull
a eles para indicar que não há valor armazenado nele, por exemplo,int? a = null;
onde o ponto de interrogação indica que é permitido armazenar nulo em variávela
. Você pode verificar isso comif (a.HasValue) {...}
ou comif (a==null) {...}
. Variáveis anuláveis, comoa
este exemplo, permitem acessar o valor viaa.Value
explicitamente, ou apenas como via normala
.Observe que acessá-lo via
a.Value
lança um emInvalidOperationException
vez de umNullReferenceException
sea
énull
- você deve fazer a verificação antecipadamente, ou seja, se você tiver outra variável anulávelint b;
, deverá fazer atribuições comoif (a.HasValue) { b = a.Value; }
ou mais curtaif (a != null) { b = a; }
.O restante deste artigo entra em mais detalhes e mostra os erros que muitos programadores cometem, o que pode levar a um
NullReferenceException
.Mais especificamente
O
runtime
jogando umNullReferenceException
sempre significa a mesma coisa: você está tentando usar uma referência, e a referência não é inicializado (ou foi uma vez inicializado, mas é não inicializado).Isso significa que a referência é
null
e você não pode acessar membros (como métodos) por meio de umanull
referência. O caso mais simples:Isso lançará um
NullReferenceException
na segunda linha porque você não pode chamar o método de instânciaToUpper()
em umastring
referência apontando paranull
.Depuração
Como você encontra a fonte de um
NullReferenceException
? Além de observar a exceção em si, que será lançada exatamente no local em que ocorre, as regras gerais de depuração no Visual Studio se aplicam: coloque pontos de interrupção estratégicos e inspecione suas variáveis , passando o mouse sobre seus nomes, abrindo um ( Rápido) Observe a janela ou use os vários painéis de depuração, como Locals e Autos.Se você deseja descobrir onde a referência está ou não está definida, clique com o botão direito do mouse no nome e selecione "Localizar todas as referências". Você pode colocar um ponto de interrupção em todos os locais encontrados e executar seu programa com o depurador conectado. Sempre que o depurador interrompe esse ponto de interrupção, é necessário determinar se você espera que a referência seja nula, inspecione a variável e verifique se ela aponta para uma instância quando você espera.
Seguindo o fluxo do programa dessa maneira, é possível encontrar o local em que a instância não deve ser nula e por que ela não está definida corretamente.
Exemplos
Alguns cenários comuns em que a exceção pode ser lançada:
Genérico
Se ref1 ou ref2 ou ref3 for nulo, você receberá a
NullReferenceException
. Se você deseja resolver o problema, descubra qual deles é nulo reescrevendo a expressão para seu equivalente mais simples:Especificamente, em
HttpContext.Current.User.Identity.Name
,HttpContext.Current
poderia ser nulo ou aUser
propriedade poderia ser nula ou aIdentity
propriedade poderia ser nula.Indireto
Se você deseja evitar a referência nula filho (Pessoa), você pode inicializá-la no construtor do objeto pai (Livro).
Inicializadores de objetos aninhados
O mesmo se aplica aos inicializadores de objetos aninhados:
Isso se traduz em
Enquanto a
new
palavra-chave é usada, ela cria apenas uma nova instância deBook
, mas não uma nova instânciaPerson
, portantoAuthor
a propriedade permanece imóvelnull
.Inicializadores de coleção aninhados
A coleção aninhada
Initializers
se comporta da mesma maneira:Isso se traduz em
O
new Person
único cria uma instância dePerson
, mas aBooks
coleção ainda énull
. AInitializer
sintaxe da coleção não cria uma coleção parap1.Books
, ela se traduz apenas nasp1.Books.Add(...)
instruções.Matriz
Elementos da matriz
Matrizes irregulares
Coleção / Lista / Dicionário
Variável de intervalo (indireto / diferido)
Eventos
classe pública Form1 {private Customer customer;
}
Isso pode ser resolvido seguindo a convenção de prefixar campos com um sublinhado:
Ciclo de vida da página ASP.NET:
Valores da sessão do ASP.NET
Modelos de exibição vazia do ASP.NET MVC
Se a exceção ocorrer ao fazer referência a uma propriedade de
@Model
em umASP.NET MVC View
, você precisará entender que issoModel
é definido no seu método de ação, quando vocêreturn
visualiza. Quando você retorna um modelo vazio (ou propriedade de modelo) do seu controlador, a exceção ocorre quando as visualizações o acessam:Ordem de criação de controle WPF e eventos
WPF
Os controles são criados durante a chamadaInitializeComponent
na ordem em que aparecem na árvore visual. ANullReferenceException
será gerado no caso de controles criados anteriormente com manipuladores de eventos etc., aquele disparo durante oInitializeComponent
qual os controles criados tardiamente serão referenciados.Por exemplo :
Aqui
comboBox1
é criado anteslabel1
. SecomboBox1_SelectionChanged
tentar referenciar `label1, ele ainda não foi criado.Alterar a ordem das declarações em
XAML
(ou seja, listarlabel1
antescomboBox1
, ignorando questões da filosofia do design, pelo menos resolveria o problemaNullReferenceException
aqui).Elenco com
as
Isso não
InvalidCastException
gera um, mas retorna anull
quando o elenco falha (e quandosomeObject
é nulo). Então, fique ciente disso.LINQ
FirstOrDefault()
eSingleOrDefault()
As versões simples
First()
eSingle()
lançam exceções quando não há nada. As versões "OrDefault" retornam nulo nesse caso. Então, fique ciente disso.para cada
foreach
lança quando você tenta iterar a coleção nula. Geralmente causado pornull
resultado inesperado de métodos que retornam coleções.Exemplo mais realista - selecione nós do documento XML. Será lançada se os nós não forem encontrados, mas a depuração inicial mostrar que todas as propriedades são válidas:
Maneiras de evitar
Verifique explicitamente
null
e ignore valores nulos.Se, às vezes, você espera que a referência seja nula, verifique
null
antes de acessar os membros da instância:Verifique explicitamente
null
e forneça um valor padrão.Chamada de métodos que você espera que uma instância possa retornar
null
, por exemplo, quando o objeto que está sendo procurado não puder ser encontrado. Você pode optar por retornar um valor padrão quando este for o caso:Verifique explicitamente as
null
chamadas de método e crie uma exceção personalizada.Você também pode lançar uma exceção personalizada, apenas para capturá-la no código de chamada:
Use
Debug.Assert
se um valor nunca deve sernull
, para capturar o problema mais cedo do que a exceção ocorre.Quando você sabe durante o desenvolvimento que um método pode, mas nunca deve retornar
null
, você pode usarDebug.Assert()
para interromper o mais rápido possível quando ocorrer:Embora essa verificação não termine na construção da versão , fazendo com que seja lançada
NullReferenceException
novamente quando estiverbook == null
em tempo de execução no modo de liberação.Use
GetValueOrDefault()
paranullable
tipos de valor para fornecer um valor padrão quando estiveremnull
.Use o operador coalescente nulo:
??
[C #] ouIf()
[VB].A abreviação para fornecer um valor padrão quando a
null
é encontrado:Use o operador de condição nula:
?.
ou?[x]
para matrizes (disponíveis em C # 6 e VB.NET 14):Às vezes, isso também é chamado de operador de navegação segura ou Elvis (após seu formato). Se a expressão no lado esquerdo do operador for nula, o lado direito não será avaliado e o nulo será retornado. Isso significa casos como este:
Se a pessoa não tiver um título, isso gerará uma exceção porque está tentando chamar
ToUpper
uma propriedade com um valor nulo.Dentro
C# 5
e abaixo, isso pode ser protegido com:Agora, a variável title será nula em vez de lançar uma exceção. O C # 6 apresenta uma sintaxe mais curta para isso:
Isso resultará na variável title
null
, e a chamada paraToUpper
não será feita, seperson.Title
fornull
.Obviamente, você ainda precisa verificar se
title
há nulo ou usar o operador de condição nula junto com o operador de coalescência nula (??
) para fornecer um valor padrão:Da mesma forma, para matrizes, você pode usar da
?[i]
seguinte maneira:Isso fará o seguinte: Se
myIntArray
for nulo, a expressão retornará nulo e você poderá verificá-la com segurança. Se ele contiver uma matriz, fará o mesmo que:elem = myIntArray[i];
e retorna oi<sup>th</sup>
elemento.Use o contexto nulo (disponível em C # 8):
Introduzido nos
C# 8
contextos nulos e nos tipos de referência anuláveis, executam análises estáticas nas variáveis e fornecem um aviso do compilador se um valor puder ser potencialmente nulo ou tiver sido definido como nulo. Os tipos de referência anuláveis permitem explicitamente que os tipos sejam nulos.O contexto de anotação anulável e o contexto de aviso anulável podem ser definidos para um projeto usando o
Nullable
elemento no seucsproj
arquivo. Este elemento configura como o compilador interpreta a nulidade dos tipos e quais avisos são gerados. As configurações válidas são:Um tipo de referência anulável é observado usando a mesma sintaxe que os tipos de valor anulável: a
?
é anexado ao tipo da variável.Técnicas especiais para depuração e correção de derefs nulos em iteradores
C#
suporta "blocos iteradores" (chamados "geradores" em outros idiomas populares). Exceções de dereferência nula podem ser particularmente difíceis de depurar em blocos de iteradores devido à execução adiada:Se
whatever
os resultados emnull
seguida,MakeFrob
vai jogar. Agora, você pode pensar que a coisa certa a fazer é:Por que isso está errado? Como o bloco iterador não é executado até o
foreach
! A chamada paraGetFrobs
simplesmente retorna um objeto que, quando iterado , executará o bloco iterador.Ao escrever uma verificação nula como essa, você evita a desreferência nula, mas move a exceção de argumento nulo para o ponto da iteração , não para o ponto da chamada , e isso é muito confuso para depuração .
A correção correta é:
Ou seja, crie um método auxiliar privado que tenha a lógica de bloco do iterador e um método de superfície pública que faça a verificação nula e retorne o iterador. Agora, quando
GetFrobs
é chamada, a verificação nula acontece imediatamente e éGetFrobsForReal
executada quando a sequência é iterada.Se você examinar a fonte de referência para
LINQ
Objetos, verá que essa técnica é usada por toda parte. É um pouco mais complicado de escrever, mas facilita muito a depuração de erros de nulidade. Otimize seu código para a conveniência do chamador, não para o autor .Uma observação sobre dereferences nulos em código não seguro
C#
possui um modo "inseguro", que, como o nome indica, é extremamente perigoso, porque os mecanismos de segurança normais que fornecem segurança de memória e segurança de tipo não são aplicados. Você não deve escrever código inseguro, a menos que tenha um entendimento profundo e profundo de como a memória funciona .No modo não seguro, você deve estar ciente de dois fatos importantes:
Para entender por que isso acontece, é útil entender como o .NET produz exceções de desreferência nula em primeiro lugar. (Esses detalhes se aplicam ao .NET em execução no Windows; outros sistemas operacionais usam mecanismos semelhantes.)
A memória é virtualizada
Windows
; cada processo obtém um espaço de memória virtual de muitas "páginas" de memória que são rastreadas pelo sistema operacional. Cada página da memória possui sinalizadores definidos que determinam como ela pode ser usada: leitura, gravação, execução etc. A página mais baixa é marcada como "produza um erro, se alguma vez for usada de alguma maneira".Um ponteiro nulo e uma referência nula
C#
são representados internamente como o número zero e, portanto, qualquer tentativa de desreferencia-lo em seu armazenamento de memória correspondente faz com que o sistema operacional produza um erro. O tempo de execução do .NET detecta esse erro e o transforma na exceção de desreferência nula.É por isso que desreferenciar um ponteiro nulo e uma referência nula produz a mesma exceção.
E o segundo ponto? Anular a referência a qualquer ponteiro inválido que caia na página mais baixa da memória virtual causa o mesmo erro do sistema operacional e, portanto, a mesma exceção.
Por que isso faz sentido? Bem, suponha que tenhamos uma estrutura contendo duas entradas e um ponteiro não gerenciado igual a nulo. Se tentarmos desreferenciar o segundo int na estrutura,
CLR
ele não tentará acessar o armazenamento no local zero; ele acessará o armazenamento no local quatro. Mas, logicamente, essa é uma dereferência nula, porque estamos chegando a esse endereço via nula.Se você estiver trabalhando com código não seguro e receber uma exceção de desreferência nula, lembre-se de que o ponteiro incorreto não precisa ser nulo. Pode ser qualquer local na página mais baixa e essa exceção será produzida.
fonte
new Book { Author = { Age = 45 } };
Como é que a inicialização interna ainda ... Não consigo pensar em uma situação em que o init interno funcionaria, mas compila e o intellisense funciona ... A menos que por estruturas?Exceção NullReference - Visual Basic
O
NullReference Exception
para Visual Basic não é diferente daquele em c # . Afinal, ambos estão relatando a mesma exceção definida no .NET Framework que ambos usam. Causas exclusivas do Visual Basic são raras (talvez apenas uma).Esta resposta usará termos, sintaxe e contexto do Visual Basic. Os exemplos usados vêm de um grande número de perguntas anteriores do Stack Overflow. Isso é para maximizar a relevância usando os tipos de situações geralmente vistas nas postagens. Um pouco mais de explicação também é fornecida para aqueles que precisam. Um exemplo semelhante ao seu é muito provável aqui.
Nota:
NullReferenceException
(NRE), como encontrá-lo, como corrigi-lo e como evitá-lo. Um NRE pode ser causado de várias maneiras, por isso é improvável que seja seu único encontro.Significado básico
A mensagem "Objeto não definido para uma instância de Objeto" significa que você está tentando usar um objeto que não foi inicializado. Isso se resume a um destes:
Encontrando a causa
Como o problema é uma referência a objeto
Nothing
, a resposta é examiná-lo para descobrir qual. Em seguida, determine por que não foi inicializado. Mantenha o mouse sobre as várias variáveis e o Visual Studio (VS) mostrará seus valores - o culpado seráNothing
.Você também deve remover todos os blocos Try / Catch do código relevante, especialmente aqueles onde não há nada no bloco Catch. Isso fará com que seu código falhe ao tentar usar um objeto que é
Nothing
. É isso que você deseja, porque identificará o local exato do problema e permitirá identificar o objeto que está causando o problema.A
MsgBox
na captura que exibeError while...
será de pouca ajuda. Esse método também leva a questões muito ruins de Stack Overflow, porque você não pode descrever a exceção real, o objeto envolvido ou mesmo a linha de código onde ela ocorre.Você também pode usar o
Locals Window
( Debug -> Windows -> Locals ) para examinar seus objetos.Depois de saber qual e onde está o problema, geralmente é bastante fácil de corrigir e mais rápido do que postar uma nova pergunta.
Veja também:
Exemplos e Remédios
Objetos de classe / Criando uma instância
O problema é que
Dim
não cria um objeto CashRegister ; apenas declara uma variável denominadareg
desse tipo. Declarar uma variável de objeto e criar uma instância são duas coisas diferentes.Remédio
O
New
operador geralmente pode ser usado para criar a instância quando você a declara:Quando é apropriado apenas criar a instância posteriormente:
Nota: Não use
Dim
novamente em um procedimento, incluindo o construtor (Sub New
):Isso criará uma variável local
reg
, que existe apenas nesse contexto (sub). Areg
variável com o nível do móduloScope
que você usará em qualquer outro lugar permaneceNothing
.Para ser claro,
Dim
(ouPrivate
) declara apenas uma variável e suaType
. O escopo da variável - se existe para todo o módulo / classe ou é local para um procedimento - é determinado pelo local em que é declarado.Private | Friend | Public
define o nível de acesso, não o escopo .Para mais informações, veja:
Matrizes
As matrizes também devem ser instanciadas:
Essa matriz foi declarada apenas, não criada. Existem várias maneiras de inicializar uma matriz:
Nota: A partir do VS 2010, ao inicializar uma matriz local usando um literal e
Option Infer
, os elementosAs <Type>
eNew
são opcionais:O tipo de dados e o tamanho da matriz são inferidos a partir dos dados que estão sendo atribuídos. Declarações nível de classe / Módulo ainda requerem
As <Type>
comOption Strict
:Exemplo: Matriz de Objetos de Classe
A matriz foi criada, mas os
Foo
objetos nela não.Remédio
Usar um
List(Of T)
tornará bastante difícil ter um elemento sem um objeto válido:Para mais informações, veja:
Listas e Coleções
As coleções do .NET (das quais existem muitas variedades - listas, dicionário etc.) também devem ser instanciadas ou criadas.
Você obtém a mesma exceção pelo mesmo motivo -
myList
foi declarado apenas, mas nenhuma instância foi criada. O remédio é o mesmo:Uma supervisão comum é uma classe que usa uma coleção
Type
:Qualquer procedimento resultará em um NRE, porque
barList
é declarado apenas, não instanciado. Criar uma instância deFoo
também não criará uma instância do internobarList
. Pode ter sido a intenção de fazer isso no construtor:Como antes, isso está incorreto:
Para mais informações, consulte
List(Of T)
Classe .Objetos do provedor de dados
Trabalhando com bancos de dados apresenta muitas oportunidades para um NullReference porque pode haver muitos objetos (
Command
,Connection
,Transaction
,Dataset
,DataTable
,DataRows
....) em uso ao mesmo tempo. Nota: Não importa qual provedor de dados você está usando - MySQL, SQL Server, OleDB etc. - os conceitos são os mesmos.Exemplo 1
Como antes, o
ds
objeto Conjunto de dados foi declarado, mas uma instância nunca foi criada. ODataAdapter
irá preencher um existenteDataSet
, não criar um. Nesse caso, comods
é uma variável local, o IDE avisa que isso pode acontecer:Quando declarado como uma variável de nível de módulo / classe, como parece ser o caso
con
, o compilador não pode saber se o objeto foi criado por um procedimento upstream. Não ignore avisos.Remédio
Exemplo 2
Um erro de digitação é um problema aqui:
Employees
vsEmployee
. Não havia umDataTable
nome "Funcionário" criado; portanto, umNullReferenceException
resultado está tentando acessá-lo. Outro problema em potencial é supor que haverá oItems
que pode não ser assim quando o SQL incluir uma cláusula WHERE.Remédio
Como isso usa uma tabela, a utilização
Tables(0)
evitará erros de ortografia. O exameRows.Count
também pode ajudar:Fill
é uma função retornando o número deRows
afetados que também pode ser testado:Exemplo 3
Ele
DataAdapter
será fornecidoTableNames
como mostrado no exemplo anterior, mas não analisa nomes da tabela SQL ou do banco de dados. Como resultado, fazds.Tables("TICKET_RESERVATION")
referência a uma tabela inexistente.O remédio é o mesmo, faça referência à tabela por índice:
Veja também DataTable Class .
Caminhos de Objeto / Aninhados
O código está testando apenas
Items
enquanto ambosmyFoo
eBar
também pode ser Nothing. O remédio é testar toda a cadeia ou caminho dos objetos, um de cada vez:AndAlso
é importante. Os testes subsequentes não serão executados quando a primeiraFalse
condição for encontrada. Isso permite que o código 'perfure' com segurança no (s) objeto (s), um 'nível' de cada vez, avaliandomyFoo.Bar
somente depois que (e se)myFoo
for determinado como válido. Cadeias ou caminhos de objetos podem ficar muito longos ao codificar objetos complexos:Não é possível fazer referência a nada 'downstream' de um
null
objeto. Isso também se aplica aos controles:Aqui,
myWebBrowser
ouDocument
poderia ser Nothing ou oformfld1
elemento pode não existir.Controles da interface do usuário
Entre outras coisas, esse código não prevê que o usuário possa não ter selecionado algo em um ou mais controles da interface do usuário.
ListBox1.SelectedItem
pode muito bem serNothing
, entãoListBox1.SelectedItem.ToString
resultará em um NRE.Remédio
Valide os dados antes de usá-los (também use
Option Strict
e parâmetros SQL):Como alternativa, você pode usar
(ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Formulários do Visual Basic
Essa é uma maneira bastante comum de obter um NRE. Em C #, dependendo de como é codificado, o IDE relatará que
Controls
não existe no contexto atual ou "não pode fazer referência a membro não estático". Então, até certo ponto, essa é uma situação apenas de VB. Também é complexo porque pode resultar em uma cascata de falha.As matrizes e coleções não podem ser inicializadas dessa maneira. Esse código de inicialização será executado antes que o construtor crie o
Form
ou oControls
. Como um resultado:somevar
atribuição resultará em uma NRE imediata porque Nothing não possui uma.Text
propriedadeA referência a elementos da matriz posteriormente resultará em um NRE. Se você fizer isso
Form_Load
, devido a um erro estranho, o IDE poderá não relatar a exceção quando isso acontecer. A exceção será exibida mais tarde quando seu código tentar usar a matriz. Essa "exceção silenciosa" é detalhada nesta postagem . Para nossos propósitos, a chave é que, quando algo catastrófico acontece ao criar um formulário (Sub New
ouForm Load
evento), as exceções podem não ser relatadas, o código sai do procedimento e apenas exibe o formulário.Como nenhum outro código no seu evento
Sub New
ouForm Load
será executado após o NRE, muitas outras coisas podem ser deixadas não inicializadas.Observe que isso se aplica a toda e qualquer referência de controle e componente, tornando-as ilegais onde estão:
Remédio Parcial
É curioso que VB não fornecer um aviso, mas o remédio é declarar os recipientes ao nível do formulário, mas inicializar -los em manipulador de eventos load forma quando os controles fazer existir. Isso pode ser feito
Sub New
desde que seu código seja após aInitializeComponent
chamada:O código do array ainda pode não estar fora de perigo. Quaisquer controles que estejam em um controle de contêiner (como um
GroupBox
ouPanel
) não serão encontradosMe.Controls
; eles estarão na coleção Controls desse Panel ou GroupBox. Um controle também não será retornado quando o nome do controle estiver incorreto ("TeStBox2"
). Nesses casos,Nothing
será novamente armazenado nesses elementos da matriz e um NRE resultará quando você tentar fazer referência a ele.Isso deve ser fácil de encontrar agora que você sabe o que está procurando:
"Button2" reside em um
Panel
Remédio
Em vez de referências indiretas por nome usando a
Controls
coleção do formulário , use a referência de controle:Função Retornando Nada
É um caso em que o IDE avisa que ' nem todos os caminhos retornam um valor e
NullReferenceException
podem resultar '. Você pode suprimir o aviso, substituindoExit Function
porReturn Nothing
, mas isso não resolve o problema. Qualquer coisa que tentar usar o retorno quandosomeCondition = False
resultará em um NRE:Remédio
Substitua
Exit Function
na função porReturn bList
. Retornar um vazioList
não é o mesmo que retornarNothing
. Se houver uma chance de um objeto retornadoNothing
, teste antes de usá-lo:Try / Catch mal implementado
Um Try / Catch mal implementado pode ocultar onde está o problema e resultar em novos:
Este é o caso de um objeto que não está sendo criado conforme o esperado, mas também demonstra a contra-utilidade de um vazio
Catch
.Há uma vírgula extra no SQL (após 'endereço de email') que resulta em uma exceção em
.ExecuteReader
. Após oCatch
não fazer nada,Finally
tenta executar a limpeza, mas como você não podeClose
umDataReader
objeto nulo ,NullReferenceException
resulta em um novo resultado.Um
Catch
bloco vazio é o playground do diabo. Este OP ficou confuso por que ele estava recebendo um NRE noFinally
bloco. Em outras situações, um vazioCatch
pode resultar em algo muito mais a jusante e fazer com que você gaste tempo olhando as coisas erradas no lugar errado para o problema. (A "exceção silenciosa" descrita acima fornece o mesmo valor de entretenimento.)Remédio
Não use blocos Try / Catch vazios - deixe o código travar para que você possa: a) identificar a causa b) identificar o local ec) aplicar um remédio adequado. Os blocos Try / Catch não têm como objetivo ocultar exceções da pessoa qualificada exclusivamente para corrigi-los - o desenvolvedor.
DBNull não é o mesmo que Nothing
A
IsDBNull
função é usada para testar se um valor é igual aSystem.DBNull
: No MSDN:Remédio
Como antes, você pode testar o Nothing e, em seguida, obter um valor específico:
Exemplo 2
FirstOrDefault
retorna o primeiro item ou o valor padrão, que éNothing
para tipos de referência e nuncaDBNull
:Controles
Se um
CheckBox
comchkName
não puder ser encontrado (ou existir em aGroupBox
),chk
será Nothing e tentar fazer referência a qualquer propriedade resultará em uma exceção.Remédio
O DataGridView
A DGV tem algumas peculiaridades vistas periodicamente:
Se
dgvBooks
tiverAutoGenerateColumns = True
, ele criará as colunas, mas não as nomeará; portanto, o código acima falhará quando as referenciar por nome.Remédio
Nomeie as colunas manualmente ou faça referência por índice:
Exemplo 2 - Cuidado com o NewRow
Quando você
DataGridView
tiverAllowUserToAddRows
comoTrue
(o padrão), o campoCells
em branco / nova linha na parte inferior conterá todosNothing
. A maioria das tentativas de usar o conteúdo (por exemploToString
) resultará em um NRE.Remédio
Use um
For/Each
loop e teste aIsNewRow
propriedade para determinar se é a última linha. Isso funciona seAllowUserToAddRows
é verdadeiro ou não:Se você usar um
For n
loop, modifique a contagem de linhas ou useExit For
quandoIsNewRow
for verdadeiro.My.Settings (StringCollection)
Sob certas circunstâncias, tentar usar um item do
My.Settings
qual é umStringCollection
pode resultar em um NullReference na primeira vez que você o usa. A solução é a mesma, mas não tão óbvia. Considerar:Como o VB está gerenciando as configurações para você, é razoável esperar que ele inicialize a coleção. Será, mas somente se você tiver adicionado anteriormente uma entrada inicial à coleção (no editor de Configurações). Como a coleção é (aparentemente) inicializada quando um item é adicionado, ela permanece
Nothing
quando não há itens no editor de Configurações a serem adicionados.Remédio
Inicialize a coleção de configurações no
Load
manipulador de eventos do formulário , se / quando necessário:Normalmente, a
Settings
coleção só precisa ser inicializada na primeira vez que o aplicativo é executado. Uma solução alternativa é adicionar um valor inicial à sua coleção em Projeto -> Configurações | FooBars , salve o projeto e remova o valor falso.Pontos chave
Você provavelmente esqueceu o
New
operador.ou
Algo que você assumiu que executaria perfeitamente para retornar um objeto inicializado ao seu código, não o fez.
Não ignore os avisos do compilador (sempre) e use
Option Strict On
(sempre).Exceção NullReference do MSDN
fonte
Outro cenário é quando você lança um objeto nulo em um tipo de valor . Por exemplo, o código abaixo:
Ele jogará um
NullReferenceException
no elenco. Parece bastante óbvio no exemplo acima, mas isso pode acontecer em cenários intrincados de "ligação tardia", em que o objeto nulo foi retornado de algum código que você não possui e a conversão é, por exemplo, gerada por algum sistema automático.Um exemplo disso é este fragmento de ligação simples do ASP.NET com o controle Calendar:
Aqui, de
SelectedDate
fato , é uma propriedade - doDateTime
tipo - do tipoCalendar
Web Control, e a ligação pode retornar perfeitamente algo nulo. O gerador implícito do ASP.NET criará um código que será equivalente ao código de conversão acima. E isso irá gerar umNullReferenceException
que é bastante difícil de detectar, porque está no código gerado pelo ASP.NET que compila bem ...fonte
DateTime x = (DateTime) o as DateTime? ?? defaultValue;
Isso significa que a variável em questão não está apontada para nada. Eu poderia gerar isso assim:
Isso lançará o erro porque, embora eu tenha declarado a variável "
connection
", ela não está apontada para nada. Quando tento ligar para o membro "Open
", não há referência para sua resolução e isso gerará o erro.Para evitar esse erro:
object == null
.A ferramenta Resharper do JetBrains identificará todos os locais em seu código que têm a possibilidade de um erro de referência nulo, permitindo que você faça uma verificação nula. Este erro é a fonte número um de bugs, IMHO.
fonte
Isso significa que seu código usou uma variável de referência de objeto que foi definida como nula (ou seja, não fez referência a uma instância de objeto real).
Para evitar o erro, os objetos que poderiam ser nulos devem ser testados quanto a nulos antes de serem utilizados.
fonte
Esteja ciente de que, independentemente do cenário, a causa é sempre a mesma no .NET:
fonte
Um exemplo dessa exceção sendo lançada é: Quando você está tentando verificar algo, isso é nulo.
Por exemplo:
O tempo de execução do .NET lançará uma NullReferenceException quando você tentar executar uma ação em algo que não foi instanciado, ou seja, o código acima.
Em comparação com um ArgumentNullException que normalmente é lançado como uma medida defensiva se um método espera que o que está sendo passado para ele não seja nulo.
Mais informações estão em C # NullReferenceException e Null Parameter .
fonte
Atualização C # 8.0, 2019: tipos de referência anuláveis
O C # 8.0 apresenta tipos de referência nulos e tipos de referência não nulos . Portanto, apenas tipos de referência anuláveis devem ser verificados para evitar uma NullReferenceException .
Se você não inicializou um tipo de referência e deseja definir ou ler uma de suas propriedades, ele lançará uma NullReferenceException .
Exemplo:
Você pode simplesmente evitar isso verificando se a variável não é nula:
Para entender completamente por que uma NullReferenceException é lançada, é importante saber a diferença entre tipos de valor e [tipos de referência] [3].
Portanto, se você estiver lidando com tipos de valor , NullReferenceExceptions não poderá ocorrer. Embora você precise manter-se alerta ao lidar com tipos de referência !
Somente tipos de referência, como o nome está sugerindo, podem conter referências ou apontar literalmente para nada (ou 'nulo'). Enquanto os tipos de valor sempre contêm um valor.
Tipos de referência (estes devem ser verificados):
Tipos de valor (você pode simplesmente ignorar estes):
fonte
Outro caso em
NullReferenceExceptions
que isso pode acontecer é o uso (incorreto) doas
operador :Aqui
Book
eCar
são tipos incompatíveis; aCar
não pode ser convertido / convertido em aBook
. Quando esse elenco falha,as
retornanull
. O usomybook
após isso causa aNullReferenceException
.Em geral, você deve usar um elenco ou
as
, da seguinte maneira:Se você espera que a conversão de tipo seja sempre bem-sucedida (ou seja, você sabe o que o objeto deve estar adiantado), use uma conversão:
Se você não tiver certeza do tipo, mas deseja tentar usá-lo como um tipo específico, use
as
:fonte
Você está usando o objeto que contém a referência de valor nulo. Portanto, está dando uma exceção nula. No exemplo, o valor da sequência é nulo e, ao verificar seu comprimento, ocorreu a exceção.
Exemplo:
O erro de exceção é:
fonte
Enquanto o que causa um NullReferenceExceptions e abordagens para evitar / corrigir essa exceção foi abordado em outras respostas, o que muitos programadores ainda não aprenderam é como depurar independentemente essas exceções durante o desenvolvimento.
No Visual Studio, isso geralmente é fácil, graças ao Visual Studio Debugger .
Primeiro, verifique se o erro correto será capturado - consulte Como permito quebras em 'System.NullReferenceException' no VS2010? Nota 1
Em seguida, inicie com Depuração (F5) ou Anexe [o VS Debugger] ao processo em execução . Ocasionalmente, pode ser útil usá-lo
Debugger.Break
, o que solicitará o lançamento do depurador.Agora, quando a NullReferenceException for lançada (ou não tratada), o depurador irá parar (lembra-se da regra definida acima?) Na linha em que ocorreu a exceção. Às vezes, o erro será fácil de detectar.
Por exemplo, na linha a seguir, o único código que pode causar a exceção é se o valor for
myString
avaliado como nulo. Isso pode ser verificado olhando para a Janela de inspeção ou executando expressões na Janela imediata .Em casos mais avançados, como o seguinte, você precisará usar uma das técnicas acima (Monitorar ou Windows Imediato) para inspecionar as expressões e determinar se
str1
foi nulo ou sestr2
foi nulo.Depois que a exceção é lançada, geralmente é trivial raciocinar para trás para descobrir onde o valor nulo foi [incorretamente] introduzido -
Aproveite o tempo necessário para entender a causa da exceção. Inspecione expressões nulas. Inspecione as expressões anteriores que poderiam ter resultado em tais expressões nulas. Adicione pontos de interrupção e siga o programa conforme apropriado. Use o depurador.
1 Se a interrupção na execução for muito agressiva e o depurador parar em um NPE na biblioteca .NET ou de terceiros, a interrupção na não tratada pelo usuário poderá ser usada para limitar as exceções capturadas. Além disso, o VS2012 apresenta Just My Code, que eu recomendo ativar também.
fonte
Simon Mourier deu este exemplo :
onde uma conversão de unboxing (conversão) de
object
(ou de uma das classesSystem.ValueType
ouSystem.Enum
, ou de um tipo de interface) para um tipo de valor (diferente deNullable<>
) em si forneceNullReferenceException
.Na outra direção, uma conversão de boxe de um
Nullable<>
que éHasValue
igualfalse
a um tipo de referência pode fornecer umanull
referência que pode posteriormente levar a aNullReferenceException
. O exemplo clássico é:Às vezes o boxe acontece de outra maneira. Por exemplo, com este método de extensão não genérico:
o código a seguir será problemático:
Esses casos surgem devido às regras especiais que o tempo de execução usa ao encaixar as
Nullable<>
instâncias.fonte
Adicionando um caso em que o nome da classe da entidade usada na estrutura da entidade é o mesmo da classe de um arquivo code-behind do formulário da web.
Suponha que você tenha um formulário da Web Contact.aspx cuja classe por trás do código seja Contato e você tenha um nome de entidade Contato.
O código a seguir lançará uma NullReferenceException quando você chamar context.SaveChanges ()
Por uma questão de completude da classe DataContext
e Classe de entidade de contato. Às vezes, as classes de entidade são classes parciais, para que você também possa estendê-las em outros arquivos.
O erro ocorre quando a entidade e a classe code-behind estão no mesmo espaço para nome. Para corrigir isso, renomeie a classe da entidade ou a classe code-behind para Contact.aspx.
Razão Ainda não tenho certeza sobre o motivo. Mas sempre que qualquer classe de entidade estender o System.Web.UI.Page, esse erro ocorre.
Para discussão, dê uma olhada em NullReferenceException em DbContext.saveChanges ()
fonte
Outro caso geral em que alguém pode receber essa exceção envolve zombar de classes durante o teste de unidade. Independentemente da estrutura de simulação usada, você deve garantir que todos os níveis apropriados da hierarquia de classes sejam simulados corretamente. Em particular, todas as propriedades
HttpContext
mencionadas pelo código em teste devem ser ridicularizadas.Consulte " NullReferenceException lançada ao testar o AuthorizationAttribute personalizado " para obter um exemplo um pouco detalhado.
fonte
Eu tenho uma perspectiva diferente para responder a isso. Esse tipo de resposta "o que mais posso fazer para evitá-lo? "
Ao trabalhar em diferentes camadas , por exemplo, em um aplicativo MVC, um controlador precisa de serviços para chamar operações de negócios. Nesses cenários, o Contêiner de injeção de dependência pode ser usado para inicializar os serviços para evitar a NullReferenceException . Isso significa que você não precisa se preocupar em procurar nulos e apenas chamar os serviços do controlador, como se eles sempre estivessem disponíveis (e inicializados) como um singleton ou um protótipo.
fonte
Sobre o assunto "o que devo fazer sobre isso" , pode haver muitas respostas.
Uma maneira mais "formal" de impedir essas condições de erro durante o desenvolvimento é aplicar o design por contrato no seu código. Isso significa que você precisa definir invariantes de classe e / ou até pré - condições e pós - condições de função / método em seu sistema durante o desenvolvimento.
Em resumo, os invariantes de classe garantem que haverá algumas restrições em sua classe que não serão violadas no uso normal (e, portanto, a classe não entrará em um estado inconsistente). As pré-condições significam que os dados fornecidos como entrada para uma função / método devem seguir algumas restrições definidas e nunca violá-las, e as pós - condições significam que uma saída da função / método deve seguir as restrições definidas novamente sem nunca violá-las. As condições do contrato nunca devem ser violadas durante a execução de um programa livre de erros; portanto, o design por contrato é verificado na prática no modo de depuração, enquanto está desabilitado nas versões , para maximizar o desempenho do sistema desenvolvido.
Dessa forma, você pode evitar
NullReferenceException
casos resultantes da violação das restrições definidas. Por exemplo, se você usar uma propriedade de objetoX
em uma classe e depois tentar chamar um de seus métodos eX
tiver um valor nulo, isso levará aNullReferenceException
:Mas se você definir "a propriedade X nunca deve ter um valor nulo" como condição prévia do método, poderá impedir o cenário descrito anteriormente:
Por essa causa, o projeto Code Contracts existe para aplicativos .NET.
Como alternativa, o design por contrato pode ser aplicado usando asserções .
ATUALIZAÇÃO: Vale ressaltar que o termo foi cunhado por Bertrand Meyer em conexão com o design da linguagem de programação Eiffel .
fonte
A
NullReferenceException
é lançada quando estamos tentando acessar as propriedades de um objeto nulo ou quando um valor de string fica vazio e estamos tentando acessar métodos de string.Por exemplo:
Quando um método de string de uma string vazia é acessado:
Quando uma propriedade de um objeto nulo é acessada:
fonte
String.Empty.ToLower()
não lançará uma exceção de referência nula. Representa uma string real, embora uma vazia (ie""
). Como isso tem um objeto para chamarToLower()
, não faria sentido lançar uma exceção de referência nula lá.TL; DR: tente usar em
Html.Partial
vez deRenderpage
Eu estava começando
Object reference not set to an instance of an object
quando tentei renderizar uma View dentro de uma View enviando um Model, assim:A depuração mostrou que o modelo era Nulo no MyOtherView. Até que eu mudei para:
E funcionou.
Além disso, o motivo pelo qual não precisei
Html.Partial
começar foi porque o Visual Studio às vezes lança linhas onduladas com aparência de erro embaixoHtml.Partial
se estiver dentro de umforeach
loop de construção diferente , mesmo que não seja realmente um erro:Mas consegui executar o aplicativo sem problemas com esse "erro". Consegui me livrar do erro alterando a estrutura do
foreach
loop para ficar assim:Embora eu tenha a sensação de que foi porque o Visual Studio estava interpretando mal os e comercial e os colchetes.
fonte
Html.Partial
, não@Html.Partial
Null
), então eu sabia que o erro estava em como eu estava enviando o modelo.O que você pode fazer sobre isso?
Há muitas boas respostas aqui explicando o que é uma referência nula e como depurá-la. Mas há muito pouco sobre como evitar o problema ou, pelo menos, facilitar a captura.
Verificar argumentos
Por exemplo, os métodos podem verificar os diferentes argumentos para ver se são nulos e lançar
ArgumentNullException
uma exceção obviamente criada para esse propósito exato.O construtor para o
ArgumentNullException
even leva o nome do parâmetro e uma mensagem como argumentos para que você possa dizer ao desenvolvedor exatamente qual é o problema.Use ferramentas
Existem também várias bibliotecas que podem ajudar. "Resharper", por exemplo, pode fornecer avisos enquanto você escreve um código, especialmente se você usar o atributo: NotNullAttribute
Existem "Contratos de código da Microsoft", nos quais você usa sintaxe como a
Contract.Requires(obj != null)
que fornece verificação de tempo de execução e compilação: Introdução aos contratos de código .Há também "PostSharp", que permitirá que você use apenas atributos como este:
Ao fazer isso e fazer do PostSharp parte do seu processo de compilação,
obj
será verificado se há nulo no tempo de execução. Consulte: Verificação nula PostSharpSolução de código simples
Ou você pode sempre codificar sua própria abordagem usando código antigo simples. Por exemplo, aqui está uma estrutura que você pode usar para capturar referências nulas. Foi modelado com o mesmo conceito de
Nullable<T>
:Você usaria muito semelhante da mesma maneira que usaria
Nullable<T>
, exceto com o objetivo de realizar exatamente o oposto - para não permitirnull
. aqui estão alguns exemplos:NotNull<T>
é convertido implicitamente para eT
para que você possa usá-lo em qualquer lugar que precisar. Por exemplo, você pode passar umPerson
objeto para um método que leva umNotNull<Person>
:Como você pode ver acima, como no caso anulável, você acessaria o valor subjacente por meio da
Value
propriedade Como alternativa, você pode usar uma conversão explícita ou implícita; pode ver um exemplo com o valor de retorno abaixo:Ou você pode até usá-lo quando o método retornar
T
(nesse casoPerson
) fazendo uma conversão. Por exemplo, o código a seguir gostaria apenas do código acima:Combinar com extensão
Combine
NotNull<T>
com um método de extensão e você pode cobrir ainda mais situações. Aqui está um exemplo de como o método de extensão pode ser:E aqui está um exemplo de como ele pode ser usado:
GitHub
Para sua referência, disponibilizei o código acima no GitHub, você pode encontrá-lo em:
https://github.com/luisperezphd/NotNull
Recurso de idioma relacionado
O C # 6.0 introduziu o "operador condicional nulo" que ajuda um pouco com isso. Com esse recurso, você pode fazer referência a objetos aninhados e, se algum deles for,
null
toda a expressão retornaránull
.Isso reduz o número de verificações nulas que você precisa fazer em alguns casos. A sintaxe é colocar um ponto de interrogação antes de cada ponto. Pegue o seguinte código, por exemplo:
Imagine que esse
country
é um objeto do tipoCountry
que possui uma propriedade chamadaState
e assim por diante. Secountry
,State
,County
, ouCity
énull
entãoaddress will be
nulo. Therefore you only have to check whether
endereçois
null`.É um ótimo recurso, mas fornece menos informações. Não torna óbvio qual dos quatro é nulo.
Incorporado como Anulável?
C # tem uma abreviação legal para
Nullable<T>
, você pode criar algo anulável colocando um ponto de interrogação após o tipoint?
.Seria bom se C # tinha algo parecido com a
NotNull<T>
estrutura acima e teve um atalho semelhante, talvez o ponto de exclamação para que você poderia escrever algo como (!):public void WriteName(Person! person)
.fonte
Curiosamente, nenhuma das respostas nesta página menciona os dois casos extremos, espero que ninguém se importe se eu os adicionar:
Caso 1 do Edge: acesso simultâneo a um dicionário
Dicionários genéricos no .NET não são seguros para threads e, às vezes, podem gerar um
NullReference
ou até (mais frequente) umKeyNotFoundException
quando você tenta acessar uma chave de dois threads simultâneos. A exceção é bastante enganosa neste caso.Caso 2 do Edge: código não seguro
Se a
NullReferenceException
é lançada pelounsafe
código, você pode examinar suas variáveis de ponteiro e verificar se háIntPtr.Zero
ou algo assim. O que é a mesma coisa ("exceção de ponteiro nulo"), mas em código inseguro, as variáveis são frequentemente convertidas em tipos / matrizes de valor, etc., e você bate a cabeça na parede, imaginando como um tipo de valor pode gerar isso. exceção.(Outro motivo para não usar código inseguro, a menos que você precise, a propósito)
fonte
null
que maneira?Você pode corrigir NullReferenceException de maneira limpa usando Operadores com condição nula no c # 6 e escrever menos código para manipular verificações nulas.
É usado para testar nulos antes de executar uma operação de acesso de membro (?.) Ou índice (? [).
Exemplo
é equivalente a:
O resultado é que o nome será nulo quando p for nulo ou quando p.Spouse for nulo.
Caso contrário, o nome da variável receberá o valor de p.Spouse.FirstName.
Para obter mais detalhes: Operadores nulos-condicionais
fonte
A linha de erro "Referência de objeto não definida para uma instância de um objeto." Afirma que você não atribuiu um objeto de instância a uma referência de objeto e ainda assim está acessando as propriedades / métodos desse objeto.
por exemplo: digamos que você tenha uma classe chamada myClass e ela contenha uma propriedade prop1.
Agora você está acessando este prop1 em alguma outra classe, como abaixo:
a linha acima gera erro porque a referência da classe myClass é declarada, mas não instanciada, ou uma instância do objeto não é atribuída à referência dessa classe.
Para corrigir isso, é necessário instanciar (atribuir objeto à referência dessa classe).
fonte
A referência NullReferenceException ou Object não definida para uma instância de um objeto ocorre quando um objeto da classe que você está tentando usar não é instanciado. Por exemplo:
Suponha que você tenha uma classe chamada Aluno.
Agora, considere outra aula em que você está tentando recuperar o nome completo do aluno.
Como visto no código acima, a instrução Student s - declara apenas a variável do tipo Student, observe que a classe Student não é instanciada neste momento. Portanto, quando a instrução s.GetFullName () for executada, ela lançará a NullReferenceException.
fonte
Bem, em termos simples:
Você está tentando acessar um objeto que não foi criado ou atualmente não está na memória.
Então, como lidar com isso:
Depure e deixe o depurador quebrar ... Ele levará você diretamente para a variável que está quebrada ... Agora sua tarefa é simplesmente corrigir isso. Usando a nova palavra-chave no local apropriado.
Se isso é causado em alguns comandos do banco de dados porque o objeto não está presente, tudo o que você precisa fazer é fazer uma verificação nula e tratá-lo:
O mais difícil .. se o GC já coletou o objeto ... Isso geralmente ocorre se você estiver tentando encontrar um objeto usando cadeias ... Ou seja, localizando-o pelo nome do objeto, pode ser que o GC já esteja limpo ... Isso é difícil de encontrar e se tornará um problema ... Uma maneira melhor de resolver isso é fazer verificações nulas sempre que necessário durante o processo de desenvolvimento. Isso economizará muito tempo.
Ao encontrar pelo nome, quero dizer que alguma estrutura permite que você FIndObjects use seqüências de caracteres e o código fique assim: FindObject ("ObjectName");
fonte
Literalmente, a maneira mais fácil de corrigir uma NullReferenceExeption tem duas maneiras. Se você tiver um GameObject, por exemplo, com um script anexado e uma variável chamada rb (rigidbody), essa variável começará nula quando você iniciar o jogo.
É por isso que você obtém um NullReferenceExeption porque o computador não possui dados armazenados nessa variável.
Vou usar uma variável RigidBody como exemplo.
Podemos adicionar dados com muita facilidade, de várias maneiras:
Em seguida, entre no seu script e digite
rb = GetComponent<Rigidbody>();
Esta linha de código funciona melhor nas suas funções
Start()
ouAwake()
.rb = AddComponent<RigidBody>();
Notas adicionais: Se você deseja que a unidade adicione um componente ao seu objeto e pode ter esquecido de adicioná-lo, digite
[RequireComponent(typeof(RigidBody))]
acima da sua declaração de classe (o espaço abaixo de todos os seus usos).Aproveite e divirta-se fazendo jogos!
fonte
Se considerarmos cenários comuns em que essa exceção pode ser lançada, acessando propriedades dentro do objeto na parte superior.
Ex:
aqui, se o endereço for nulo, você receberá NullReferenceException.
Portanto, como prática, devemos sempre usar a verificação nula, antes de acessar propriedades em tais objetos (especialmente em genéricos)
fonte
Isso é basicamente uma exceção de referência nula . Como a Microsoft declara
O que isso significa?
Isso significa que, se algum membro que não possui nenhum valor e nós o obrigarmos a executar determinada tarefa, o sistema sem dúvida lançará uma mensagem e dirá:
"Ei, espere, esse membro não tem valores, portanto não pode executar a tarefa que você está entregando."
A própria exceção diz que algo está sendo referido, mas cujo valor não está sendo definido. Portanto, isso indica que isso ocorre apenas ao usar tipos de referência, pois os tipos Value não podem ser nulos.
NullReferenceException não ocorrerá se estivermos usando membros do tipo Valor.
O código acima mostra uma sequência simples que é atribuída com um valor nulo .
Agora, quando tento imprimir o comprimento da string str , recebo uma mensagem sem exceção do tipo 'System.NullReferenceException', porque o membro str está apontando para nulo e não pode haver nenhum tamanho nulo.
' NullReferenceException ' também ocorre quando esquecemos de instanciar um tipo de referência.
Suponha que eu tenha um método de classe e membro. Não instanciei minha classe, mas apenas nomeiei minha classe. Agora, se eu tentar usar o método, o compilador lançará um erro ou emitirá um aviso (dependendo do compilador).
O compilador para o código acima gera um erro de que a variável obj não está atribuída, o que significa que nossa variável tem valores nulos ou nada. O compilador para o código acima gera um erro de que a variável obj não está atribuída, o que significa que nossa variável tem valores nulos ou nada.
Por que isso ocorre?
NullReferenceException surge devido a nossa falha por não verificar o valor do objeto. Geralmente, deixamos os valores do objeto desmarcados no desenvolvimento do código.
Também surge quando esquecemos de instanciar nossos objetos. O uso de métodos, propriedades, coleções etc. que podem retornar ou definir valores nulos também pode ser a causa dessa exceção.
Como isso pode ser evitado?
Existem várias maneiras e métodos para evitar essa renomada exceção:
Verificação explícita: Devemos seguir a tradição de verificar os objetos, propriedades, métodos, matrizes e coleções, sejam eles nulos. Isso pode ser simplesmente implementado usando instruções condicionais como if-else se-else etc.
Tratamento de exceções: uma das maneiras importantes de gerenciar essa exceção. Usando blocos simples try-catch-finalmente, podemos controlar essa exceção e também manter um log dela. Isso pode ser muito útil quando seu aplicativo estiver no estágio de produção.
Operadores nulos: O operador nulo de coalescência e os operadores condicionais nulos também podem ser úteis ao definir valores para objetos, variáveis, propriedades e campos.
Depurador: Para os desenvolvedores, temos a grande arma de depuração conosco. Se enfrentamos NullReferenceException durante o desenvolvimento, podemos usar o depurador para chegar à fonte da exceção.
Método interno: métodos do sistema, como GetValueOrDefault (), IsNullOrWhiteSpace () e IsNullorEmpty (), procuram nulos e atribuem o valor padrão se houver um valor nulo.
Já existem muitas boas respostas aqui. Você também pode verificar uma descrição mais detalhada com exemplos no meu blog .
Espero que isso ajude também!
fonte
Se alguém receber esta mensagem durante o salvamento ou compilação da compilação, feche todos os arquivos e abra qualquer arquivo para compilar e salvar.
Para mim, o motivo foi que eu havia renomeado o arquivo e o arquivo antigo ainda estava aberto.
fonte