Verificar se um objecto é nulo em C#
gostaria de impedir o processamento de um objecto se este for nulo.
no seguinte código, verifico se o objecto é nulo por:
if (!data.Equals(null))
e
if (data != null)
No entanto, recebo um NullReferenceException
em dataList.Add(data)
. Se o objeto foi nulo, ele nunca deveria ter sequer entrado na declaração if
!
Assim, estou a perguntar se esta é a maneira correcta de verificar se um objecto é nulo:
public List<Object> dataList;
public bool AddData(ref Object data)
bool success = false;
try
{
// I've also used "if (data != null)" which hasn't worked either
if (!data.Equals(null))
{
//NullReferenceException occurs here ...
dataList.Add(data);
success = doOtherStuff(data);
}
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
return success;
}
Se esta é a forma correcta de verificar se o objecto é nulo, o que estou a fazer? errado (Como posso evitar o processamento adicional no objeto para evitar a Isenção de realimentação)?
12 answers
data
isso é null
, mas dataList
.
Você precisa criar um com
public List<Object> dataList = new List<Object>();
Ainda melhor: já que é um campo, faça-o private
. E se não há nada que te impeça, fá-lo também. É só um bom treino.
De lado.
A forma correcta de verificar a nulidade é if(data != null)
. Este tipo de controlo é omnipresente para tipos de referência; mesmo Nullable<T>
sobrepõe-se ao operador da igualdade para ser uma forma mais conveniente de expressar nullable.HasValue
ao verificar nulidade.
Se o fizeres {[10] } então terás um NullReferenceException
se data == null
. O que é um pouco cómico, já que evitar esta excepção era o objectivo em primeiro lugar.
Também estás a fazer isto:
catch (Exception e)
{
throw new Exception(e.ToString());
}
Isto não é nada bom. Eu posso imaginar que você colocá-lo lá apenas para que você possa quebrar no depurador enquanto ainda dentro do método, caso em que ignorar este parágrafo. Caso contrário, não apanhes excepções por nada. E se o fizer, repense-os usando apenas throw;
.
C# 6 tem verificação monádica nula :)
Antes de:
if (points != null) {
var next = points.FirstOrDefault();
if (next != null && next.X != null) return next.X;
}
return -1;
Depois de:
var bestValue = points?.FirstOrDefault()?.X ?? -1;
O seu dataList é nulo porque não foi instanciado, a julgar pelo código que publicou.
Tenta:
public List<Object> dataList = new List<Object>();
public bool AddData(ref Object data)
bool success = false;
try
{
if (!data.Equals(null)) // I've also used if(data != null) which hasn't worked either
{
dataList.Add(data); //NullReferenceException occurs here
success = doOtherStuff(data);
}
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
return success;
}
[editado para reflectir a sugestão de @kelton52]
A maneira mais simples é fazer object.ReferenceEquals(null, data)
Uma vez que {[2] } não é garantido que funcione:
class Nully
{
public static bool operator ==(Nully n, object o)
{
Console.WriteLine("Comparing '" + n + "' with '" + o + "'");
return true;
}
public static bool operator !=(Nully n, object o) { return !(n==o); }
}
void Main()
{
var data = new Nully();
Console.WriteLine(null == data);
Console.WriteLine(object.ReferenceEquals(null, data));
}
Produz:
Comparando " com 'Nully'
Verdadeiro
Falso
Não, devias estar a usar {[[0]}. Se data
for realmente nulo, então o seu programa irá simplesmente estoirar com um NullReferenceException
como resultado de tentar chamar o método Equals
em null
. Perceba também que, se você quiser verificar especificamente a igualdade de referência, você deve usar o método Object.ReferenceEquals
Como você nunca sabe como Equals
foi implementado.
O teu programa está a falhar porque dataList
é nulo porque nunca o inicializas.
O problema neste caso não é que data
seja nulo. É que dataList
em si é nulo.
No local onde declara dataList
deve criar um novo objecto List
e atribuí - lo à variável.
List<object> dataList = new List<object>();
Em C # 7 o melhor é
if (obj is null)
...
Isto vai ignorar qualquer == or != definido pelo objeto (a menos, claro, que você queira usá-los ...)
Pois não podes if (!(obj is null))
(feio)
Além de @Jose Ortega resposta, seu melhor uso método de extensão
public static bool IsNull(this object T)
{
return T == null;
}
E usar IsNull
método para todos os objectos como:
object foo = new object(); //or any object from any class
if (foo.IsNull())
{
// blah blah //
}
Existe também outro problema com o seu código: está a usar a palavra-chave ref, o que significa que os dados do argumento não podem ser nulos! O MSDN diz:
Um argumento passado para um parâmetro ref deve ser inicializado primeiro. Isto difere de fora, cujos argumentos não precisam ser iniciados explicitamente antes de serem passados
Também não é uma boa ideia usar genéricos com o tipo `Objecto´. Os genéricos devem evitar o boxe / desligamento e também garantir a segurança do tipo. Se você quer um tipo comum faça seu método genérico. Finalmente o seu código deve ser assim:
public class Foo<T> where T : MyTypeOrInterface {
public List<T> dataList = new List<T>();
public bool AddData(ref T data) {
bool success = false;
try {
dataList.Add(data);
success = doOtherStuff(data);
} catch (Exception e) {
throw new Exception(e.ToString());
}
return success;
}
private bool doOtherStuff(T data) {
//...
}
}
Como outros já salientaram, não é {[[0]} mas muito provável dataList
que seja null
. Além disso...
catch
-throw
é um antipattern que quase sempre me dá vontade de vomitar sempre que o vejo. Imagine que algo corre mal profundamente em algo que doOtherStuff()
chama. Tudo o que tens de volta é um objecto, atirado ao throw
em AddData()
. Nenhum traço de pilha, nenhuma informação de chamada, nenhum Estado, nada para indicar a verdadeira fonte do problema, a menos que você vá entre e mude o seu depurador para quebrar a excepção lançada em vez de a abrir. Se você está pegando uma exceção e apenas re-jogando-a de qualquer forma, particularmente se o código no bloco de tentativa é de alguma forma não trivial, faça a si mesmo (e seus colegas, presente e futuro) um favor e jogue fora todo o bloco de teste try
-catch
block. Concedido, throw;
é melhor do que as alternativas, mas você ainda está dando a si mesmo (ou quem quer que esteja tentando corrigir um bug no código) completamente dores de cabeça desnecessárias. Isto não quer dizer que tentar atirar seja necessariamente mau por si só, desde que você faça algo relevante com o objeto de exceção que foi jogado dentro do bloco de captura.
null
. Eu não sou positivo se esta é uma preocupação ou não (pode não ser), mas parece que vale a pena olhar para fora.
public static bool isnull(object T)
{
return T == null ? true : false;
}
Utilizar:
isnull(object.check.it)
Uso condicional:
isnull(object.check.it) ? DoWhenItsTrue : DoWhenItsFalse;
Actualização (de outra forma) actualizada 08/31/2017. Obrigado pelo comentário.
public static bool isnull(object T)
{
return T ? true : false;
}
Sempre que estiver a criar objectos de classe, terá de verificar se o objecto é nulo ou não usando o código abaixo.
Exemplo: o objectivo 1 é objecto da classevoid myFunction(object1)
{
if(object1!=null)
{
object1.value1 //If we miss the null check then here we get the Null Reference exception
}
}