Related
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I am receiving this error and I'm not sure what it means?
Object reference not set to an instance of an object.
Variables in .NET are either reference types or value types. Value types are primitives such as integers and booleans or structures (and can be identified because they inherit from System.ValueType). Boolean variables, when declared, have a default value:
bool mybool;
//mybool == false
Reference types, when declared, do not have a default value:
class ExampleClass
{
}
ExampleClass exampleClass; //== null
If you try to access a member of a class instance using a null reference then you get a System.NullReferenceException. Which is the same as Object reference not set to an instance of an object.
The following code is a simple way of reproducing this:
static void Main(string[] args)
{
var exampleClass = new ExampleClass();
var returnedClass = exampleClass.ExampleMethod();
returnedClass.AnotherExampleMethod(); //NullReferenceException here.
}
class ExampleClass
{
public ReturnedClass ExampleMethod()
{
return null;
}
}
class ReturnedClass
{
public void AnotherExampleMethod()
{
}
}
This is a very common error and can occur because of all kinds of reasons. The root cause really depends on the specific scenario that you've encountered.
If you are using an API or invoking methods that may return null then it's important to handle this gracefully. The main method above can be modified in such a way that the NullReferenceException should never be seen by a user:
static void Main(string[] args)
{
var exampleClass = new ExampleClass();
var returnedClass = exampleClass.ExampleMethod();
if (returnedClass == null)
{
//throw a meaningful exception or give some useful feedback to the user!
return;
}
returnedClass.AnotherExampleMethod();
}
All of the above really just hints of .NET Type Fundamentals, for further information I'd recommend either picking up CLR via C# or reading this MSDN article by the same author - Jeffrey Richter. Also check out, much more complex, example of when you can encounter a NullReferenceException.
Some teams using Resharper make use of JetBrains attributes to annotate code to highlight where nulls are (not) expected.
In a nutshell it means.. You are trying to access an object without instantiating it.. You might need to use the "new" keyword to instantiate it first i.e create an instance of it.
For eg:
public class MyClass
{
public int Id {get; set;}
}
MyClass myClass;
myClass.Id = 0; <----------- An error will be thrown here.. because myClass is null here...
You will have to use:
myClass = new MyClass();
myClass.Id = 0;
Hope I made it clear..
Another easy way to get this:
Person myPet = GetPersonFromDatabase();
// check for myPet == null... AND for myPet.PetType == null
if ( myPet.PetType == "cat" ) <--- fall down go boom!
Not to be blunt but it means exactly what it says. One of your object references is NULL. You'll see this when you try and access the property or method of a NULL'd object.
It means you did something like this.
Class myObject = GetObjectFromFunction();
And without doing
if(myObject!=null), you go ahead do myObject.Method();
If I have the class:
public class MyClass
{
public void MyMethod()
{
}
}
and I then do:
MyClass myClass = null;
myClass.MyMethod();
The second line throws this exception becuase I'm calling a method on a reference type object that is null (I.e. has not been instantiated by calling myClass = new MyClass())
Most of the time, when you try to assing value into object, and if the value is null, then this kind of exception occur.
Please check this link.
for the sake of self learning, you can put some check condition. like
if (myObj== null)
Console.Write("myObj is NULL");
what does this error mean? Object reference not set to an instance of an object.
exactly what it says, you are trying to use a null object as if it was a properly
referenced object.
I have a generic method defined like this:
public void MyMethod<T>(T myArgument)
The first thing I want to do is check if the value of myArgument is the default value for that type, something like this:
if (myArgument == default(T))
But this doesn't compile because I haven't guaranteed that T will implement the == operator. So I switched the code to this:
if (myArgument.Equals(default(T)))
Now this compiles, but will fail if myArgument is null, which is part of what I'm testing for. I can add an explicit null check like this:
if (myArgument == null || myArgument.Equals(default(T)))
Now this feels redundant to me. ReSharper is even suggesting that I change the myArgument == null part into myArgument == default(T) which is where I started. Is there a better way to solve this problem?
I need to support both references types and value types.
To avoid boxing, the best way to compare generics for equality is with EqualityComparer<T>.Default. This respects IEquatable<T> (without boxing) as well as object.Equals, and handles all the Nullable<T> "lifted" nuances. Hence:
if(EqualityComparer<T>.Default.Equals(obj, default(T))) {
return obj;
}
This will match:
null for classes
null (empty) for Nullable<T>
zero/false/etc for other structs
How about this:
if (object.Equals(myArgument, default(T)))
{
//...
}
Using the static object.Equals() method avoids the need for you to do the null check yourself. Explicitly qualifying the call with object. probably isn't necessary depending on your context, but I normally prefix static calls with the type name just to make the code more soluble.
I was able to locate a Microsoft Connect article that discusses this issue in some detail:
Unfortunately, this behavior is by design and there is not an easy solution to enable use of with type parameters that may contain value types.
If the types are known to be reference types, the default overload of defined on object tests variables for reference equality, although a type may specify its own custom overload. The compiler determines which overload to use based on the static type of the variable (the determination is not polymorphic). Therefore, if you change your example to constrain the generic type parameter T to a non-sealed reference type (such as Exception), the compiler can determine the specific overload to use and the following code would compile:
public class Test<T> where T : Exception
If the types are known to be value types, performs specific value equality tests based on the exact types used. There is no good "default" comparison here since reference comparisons are not meaningful on value types and the compiler cannot know which specific value comparison to emit. The compiler could emit a call to ValueType.Equals(Object) but this method uses reflection and is quite inefficient compared to the specific value comparisons. Therefore, even if you were to specify a value-type constraint on T, there is nothing reasonable for the compiler to generate here:
public class Test<T> where T : struct
In the case you presented, where the compiler does not even know whether T is a value or reference type, there is similarly nothing to generate that would be valid for all possible types. A reference comparison would not be valid for value types and some sort of value comparison would be unexpected for reference types that do not overload.
Here is what you can do...
I have validated that both of these methods work for a generic comparison of reference and value types:
object.Equals(param, default(T))
or
EqualityComparer<T>.Default.Equals(param, default(T))
To do comparisons with the "==" operator you will need to use one of these methods:
If all cases of T derive from a known base class you can let the compiler know using generic type restrictions.
public void MyMethod<T>(T myArgument) where T : MyBase
The compiler then recognizes how to perform operations on MyBase and will not throw the "Operator '==' cannot be applied to operands of type 'T' and 'T'" error that you are seeing now.
Another option would be to restrict T to any type that implements IComparable.
public void MyMethod<T>(T myArgument) where T : IComparable
And then use the CompareTo method defined by the IComparable interface.
Try this:
if (EqualityComparer<T>.Default.Equals(myArgument, default(T)))
that should compile, and do what you want.
(Edited)
Marc Gravell has the best answer, but I wanted to post a simple code snippet I worked up to demonstrate it. Just run this in a simple C# console app:
public static class TypeHelper<T>
{
public static bool IsDefault(T val)
{
return EqualityComparer<T>.Default.Equals(obj,default(T));
}
}
static void Main(string[] args)
{
// value type
Console.WriteLine(TypeHelper<int>.IsDefault(1)); //False
Console.WriteLine(TypeHelper<int>.IsDefault(0)); // True
// reference type
Console.WriteLine(TypeHelper<string>.IsDefault("test")); //False
Console.WriteLine(TypeHelper<string>.IsDefault(null)); //True //True
Console.ReadKey();
}
One more thing: can someone with VS2008 try this as an extension method? I'm stuck with 2005 here and I'm curious to see if that would be allowed.
Edit: Here is how to get it working as an extension method:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// value type
Console.WriteLine(1.IsDefault());
Console.WriteLine(0.IsDefault());
// reference type
Console.WriteLine("test".IsDefault());
// null must be cast to a type
Console.WriteLine(((String)null).IsDefault());
}
}
// The type cannot be generic
public static class TypeHelper
{
// I made the method generic instead
public static bool IsDefault<T>(this T val)
{
return EqualityComparer<T>.Default.Equals(val, default(T));
}
}
To handle all types of T, including where T is a primitive type, you'll need to compile in both methods of comparison:
T Get<T>(Func<T> createObject)
{
T obj = createObject();
if (obj == null || obj.Equals(default(T)))
return obj;
// .. do a bunch of stuff
return obj;
}
Extension method based on accepted answer.
public static bool IsDefault<T>(this T inObj)
{
return EqualityComparer<T>.Default.Equals(inObj, default);
}
Usage:
private bool SomeMethod(){
var tValue = GetMyObject<MyObjectType>();
if (tValue == null || tValue.IsDefault()) return false;
}
Alternate with null to simplify:
public static bool IsNullOrDefault<T>(this T inObj)
{
if (inObj == null) return true;
return EqualityComparer<T>.Default.Equals(inObj, default);
}
Usage:
private bool SomeMethod(){
var tValue = GetMyObject<MyObjectType>();
if (tValue.IsNullOrDefault()) return false;
}
There is going to be a problem here -
If you're going to allow this to work for any type, default(T) will always be null for reference types, and 0 (or struct full of 0) for value types.
This is probably not the behavior you're after, though. If you want this to work in a generic way, you probably need to use reflection to check the type of T, and handle value types different than reference types.
Alternatively, you could put an interface constraint on this, and the interface could provide a way to check against the default of the class/struct.
I think you probably need to split this logic into two parts and check for null first.
public static bool IsNullOrEmpty<T>(T value)
{
if (IsNull(value))
{
return true;
}
if (value is string)
{
return string.IsNullOrEmpty(value as string);
}
return value.Equals(default(T));
}
public static bool IsNull<T>(T value)
{
if (value is ValueType)
{
return false;
}
return null == (object)value;
}
In the IsNull method, we're relying on the fact that ValueType objects can't be null by definition so if value happens to be a class which derives from ValueType, we already know it's not null. On the other hand, if it's not a value type then we can just compare value cast to an object against null. We could avoid the check against ValueType by going straight to a cast to object, but that would mean that a value type would get boxed which is something we probably want to avoid since it implies that a new object is created on the heap.
In the IsNullOrEmpty method, we're checking for the special case of a string. For all other types, we're comparing the value (which already know is not null) against it's default value which for all reference types is null and for value types is usually some form of zero (if they're integral).
Using these methods, the following code behaves as you might expect:
class Program
{
public class MyClass
{
public string MyString { get; set; }
}
static void Main()
{
int i1 = 1; Test("i1", i1); // False
int i2 = 0; Test("i2", i2); // True
int? i3 = 2; Test("i3", i3); // False
int? i4 = null; Test("i4", i4); // True
Console.WriteLine();
string s1 = "hello"; Test("s1", s1); // False
string s2 = null; Test("s2", s2); // True
string s3 = string.Empty; Test("s3", s3); // True
string s4 = ""; Test("s4", s4); // True
Console.WriteLine();
MyClass mc1 = new MyClass(); Test("mc1", mc1); // False
MyClass mc2 = null; Test("mc2", mc2); // True
}
public static void Test<T>(string fieldName, T field)
{
Console.WriteLine(fieldName + ": " + IsNullOrEmpty(field));
}
// public static bool IsNullOrEmpty<T>(T value) ...
// public static bool IsNull<T>(T value) ...
}
I use:
public class MyClass<T>
{
private bool IsNull()
{
var nullable = Nullable.GetUnderlyingType(typeof(T)) != null;
return nullable ? EqualityComparer<T>.Default.Equals(Value, default(T)) : false;
}
}
Just a hacky answer and as a reminder for myself.
But I find this quite helpful for my project.
The reason I write it like this is that because I don't want default integer 0 being marked as null if the value is 0
private static int o;
public static void Main()
{
//output: IsNull = False -> IsDefault = True
Console.WriteLine( "IsNull = " + IsNull( o ) + " -> IsDefault = " + IsDefault(o));
}
public static bool IsNull<T>(T paramValue)
{
if( string.IsNullOrEmpty(paramValue + "" ))
return true;
return false;
}
public static bool IsDefault<T>(T val)
{
return EqualityComparer<T>.Default.Equals(val, default(T));
}
Don't know if this works with your requirements or not, but you could constrain T to be a Type that implements an interface such as IComparable and then use the ComparesTo() method from that interface (which IIRC supports/handles nulls) like this:
public void MyMethod<T>(T myArgument) where T : IComparable
...
if (0 == myArgument.ComparesTo(default(T)))
There are probably other interfaces that you could use as well IEquitable, etc.
#ilitirit:
public class Class<T> where T : IComparable
{
public T Value { get; set; }
public void MyMethod(T val)
{
if (Value == val)
return;
}
}
Operator '==' cannot be applied to operands of type 'T' and 'T'
I can't think of a way to do this without the explicit null test followed by invoking the Equals method or object.Equals as suggested above.
You can devise a solution using System.Comparison but really that's going to end up with way more lines of code and increase complexity substantially.
I think you were close.
if (myArgument.Equals(default(T)))
Now this compiles, but will fail if myArgument is null, which is part of what I'm testing for. I can add an explicit null check like this:
You just need to reverse the object on which the equals is being called for an elegant null-safe approach.
default(T).Equals(myArgument);
Looking for some best-practice guidance. Let's say I have a line of code like this:
Color color = someOrder.Customer.LastOrder.Product.Color;
where Customer, LastOrder, Product, and Color could be null under normal conditions. I'd like color to be null if any one of the objects in the path is null, however; in order to avoid null reference exceptions, I'd need to check for the null condition for each one of the objects, e.g.
Color color = someOrder == null ||
someOrder.Customer == null ||
someOrder.Customer.LastOrder == null ||
someOrder.Customer.Product == null ?
null : someOrder.Customer.LastOrder.Product.Color;
or I could do this
Color color = null;
try {color = someOrder.Customer.LastOrder.Product.Color}
catch (NullReferenceException) {}
The first method clearly works, but it seems a bit more tedious to code and harder to read. The second way is a bit easier but probably not a good idea to use exception handling for this.
Is there another shortcut way of checking for nulls and assigning null to color if necessary? Or any thoughts on how to avoid NullReferenceExceptions when using such nested references?
You are looking for the null-safe dereferencing operator.
Color color = someOrder?.Customer?.LastOrder?.Product?.Color;
Unfortunately C# doesn't support it. Maybe it will be added later, but there are no plans to do that at the moment.
Related
Deep null checking, is there a better way?
Best practice is to follow Law of Demeter which sounds as: don't talk to strangers. I.e. object should avoid invoking methods of a member object returned by another method. This allows to write less coupled, more maintainable and readable code.
So, avoid using 'train wrecks' like someOrder.Customer.LastOrder.Product.Color, because they completely violate Law of Demeter. It's even hard to understand what business meaning this code has. Why are you getting color of product of some other order, which is not the current one?
Possible way to remove train wreck - push functionality closer to interesting end of wreck. In your case, also consider passing last product to your method, instead of using some order.
where you need to achieve this do this.
Usage
Color color = someOrder.ComplexGet(x => x.Customer.LastOrder.Product.Color);
or
Color color = Complex.Get(() => someOrder.Customer.LastOrder.Product.Color);
Helper Class Implementation
public static class Complex
{
public static T1 ComplexGet<T1, T2>(this T2 root, Func<T2, T1> func)
{
return Get(() => func(root));
}
public static T Get<T>(Func<T> func)
{
try
{
return func();
}
catch (Exception)
{
return default(T);
}
}
}
I would definitely prefer the first method... the second one exploits the exception mechanism for program flow which is bad practice IMHO...
AFAIK there is no shortcut or "null-safe dereferencing operator" in C# .
Define unique method for accessing nested properties.
For example like this
private Customoer GetCustomer(Order order)
{
return order != null ? order.Customer : null;
}
private Order GetLastOrder(Customer customer)
{
return customer != null ? customer.LastOrder : null;
}
Using the defined method access your properties across the application
You can also use the Null-conditional operator in an if statement. Really useful if there is a lot of nested values.
Example:
public class DummyDto
{
public string Name { get; set; }
public DummyDto Parent { get; set; }
}
class Program
{
static void Main(string[] args)
{
var dummyDto = new DummyDto();
//Both if statements will be true below
if(dummyDto.Parent?.Name == null)
{
Console.WriteLine("DummyDto is null");
}
if (dummyDto.Parent == null || dummyDto.Parent.Name == null)
{
Console.WriteLine("DummyDto is null");
}
}
}
Background
Let's say I have the following class:
public class MyValue<T>
{
public T Value { get; set; }
public static bool operator ==(MyValue<T> first, MyValue<T> second)
{
// if first and second are the same instance, they are equal
if (object.Equals(first, second))
{
return true;
}
// for each of the objects, get a value indicating whether either
// the object or its Value property is null
bool firstIsNull = object.Equals(first, null) ? true : first.Value == null;
bool secondIsNull = object.Equals(second, null) ? true : second.Value == null;
// if both are null, they are equal
if (firstIsNull && secondIsNull)
{
return true;
}
// Not both are null. If one is, they are not equal
if (firstIsNull || secondIsNull)
{
return false;
}
// Neither first nor second is null; compare their values
return first.Value.Equals(second.Value);
}
// more code implementing !=, Equals, GetHashCode, implicit conversions and so on
}
This class will be used as the type on properties in an object model. An object could look like so:
public class SomeClass
{
public SomeClass()
{
SomeValue = new MyValue<string>();
}
public MyValue<string> SomeValue { get; set; }
}
The idea with this is that the class simply represents the value of its Value property. It has some more functionality that is stripped away since it's not relevant for the question (some validation and stuff). Since the class has no value in itself, we want it to be as little intrusive as possible when used. Implicit conversions allows for code like this:
SomeClass instance = new SomeClass();
instance.SomeValue = "my string";
...and the question:
The idea with overloading the == (and !=) operator is to have an instance of the object where Value is null to compare equal to null (partly because we feel it makes sense, partly because of backwards compatibility issues in the object model):
MyValue<string> a = new MyValue<string>();
MyValue<string> b = null;
bool areTheyEqual = (a == b); // this will be true
This may of course seem a bit confusing, but given that MyClass is simply a wrapper, that in most of the code will be rather invisible, does it make sense to you too, or is it something really bad that we will regret for reasons that we overlooked?
In my opinion, == operator in C# is already confusing enough. If you overload it like that, you'll be increasing the possibility of confusion.
Class c = somethingEqualsToNullButNotNull;
if (c == null) { // true
}
object co = c;
if (co == null) { // false. WTF!?
}
You say you've already overridden Equals to provide the same behaviour. That means you've already broken the contract for Equals, which explicitly states:
- x.Equals(a null reference (Nothing in Visual Basic)) returns false.
Basically: no, don't do this. It will be confusing to users of the class.
Now Nullable<T> appears to break this rule:
int? x = new int?(); // Or int? x = null;
object o = null;
Console.WriteLine(x.Equals(o)); // True
... but in this case x isn't a reference, which is part of the contract description. The only way of making x a reference is to box the value, at which point x is null anyway. In your case, MyValue is a class so you can have a non-null reference which violates the contract.
If you override ==, then normally it is best to override .Equals to use the same logic.
I have a generic method defined like this:
public void MyMethod<T>(T myArgument)
The first thing I want to do is check if the value of myArgument is the default value for that type, something like this:
if (myArgument == default(T))
But this doesn't compile because I haven't guaranteed that T will implement the == operator. So I switched the code to this:
if (myArgument.Equals(default(T)))
Now this compiles, but will fail if myArgument is null, which is part of what I'm testing for. I can add an explicit null check like this:
if (myArgument == null || myArgument.Equals(default(T)))
Now this feels redundant to me. ReSharper is even suggesting that I change the myArgument == null part into myArgument == default(T) which is where I started. Is there a better way to solve this problem?
I need to support both references types and value types.
To avoid boxing, the best way to compare generics for equality is with EqualityComparer<T>.Default. This respects IEquatable<T> (without boxing) as well as object.Equals, and handles all the Nullable<T> "lifted" nuances. Hence:
if(EqualityComparer<T>.Default.Equals(obj, default(T))) {
return obj;
}
This will match:
null for classes
null (empty) for Nullable<T>
zero/false/etc for other structs
How about this:
if (object.Equals(myArgument, default(T)))
{
//...
}
Using the static object.Equals() method avoids the need for you to do the null check yourself. Explicitly qualifying the call with object. probably isn't necessary depending on your context, but I normally prefix static calls with the type name just to make the code more soluble.
I was able to locate a Microsoft Connect article that discusses this issue in some detail:
Unfortunately, this behavior is by design and there is not an easy solution to enable use of with type parameters that may contain value types.
If the types are known to be reference types, the default overload of defined on object tests variables for reference equality, although a type may specify its own custom overload. The compiler determines which overload to use based on the static type of the variable (the determination is not polymorphic). Therefore, if you change your example to constrain the generic type parameter T to a non-sealed reference type (such as Exception), the compiler can determine the specific overload to use and the following code would compile:
public class Test<T> where T : Exception
If the types are known to be value types, performs specific value equality tests based on the exact types used. There is no good "default" comparison here since reference comparisons are not meaningful on value types and the compiler cannot know which specific value comparison to emit. The compiler could emit a call to ValueType.Equals(Object) but this method uses reflection and is quite inefficient compared to the specific value comparisons. Therefore, even if you were to specify a value-type constraint on T, there is nothing reasonable for the compiler to generate here:
public class Test<T> where T : struct
In the case you presented, where the compiler does not even know whether T is a value or reference type, there is similarly nothing to generate that would be valid for all possible types. A reference comparison would not be valid for value types and some sort of value comparison would be unexpected for reference types that do not overload.
Here is what you can do...
I have validated that both of these methods work for a generic comparison of reference and value types:
object.Equals(param, default(T))
or
EqualityComparer<T>.Default.Equals(param, default(T))
To do comparisons with the "==" operator you will need to use one of these methods:
If all cases of T derive from a known base class you can let the compiler know using generic type restrictions.
public void MyMethod<T>(T myArgument) where T : MyBase
The compiler then recognizes how to perform operations on MyBase and will not throw the "Operator '==' cannot be applied to operands of type 'T' and 'T'" error that you are seeing now.
Another option would be to restrict T to any type that implements IComparable.
public void MyMethod<T>(T myArgument) where T : IComparable
And then use the CompareTo method defined by the IComparable interface.
Try this:
if (EqualityComparer<T>.Default.Equals(myArgument, default(T)))
that should compile, and do what you want.
(Edited)
Marc Gravell has the best answer, but I wanted to post a simple code snippet I worked up to demonstrate it. Just run this in a simple C# console app:
public static class TypeHelper<T>
{
public static bool IsDefault(T val)
{
return EqualityComparer<T>.Default.Equals(obj,default(T));
}
}
static void Main(string[] args)
{
// value type
Console.WriteLine(TypeHelper<int>.IsDefault(1)); //False
Console.WriteLine(TypeHelper<int>.IsDefault(0)); // True
// reference type
Console.WriteLine(TypeHelper<string>.IsDefault("test")); //False
Console.WriteLine(TypeHelper<string>.IsDefault(null)); //True //True
Console.ReadKey();
}
One more thing: can someone with VS2008 try this as an extension method? I'm stuck with 2005 here and I'm curious to see if that would be allowed.
Edit: Here is how to get it working as an extension method:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// value type
Console.WriteLine(1.IsDefault());
Console.WriteLine(0.IsDefault());
// reference type
Console.WriteLine("test".IsDefault());
// null must be cast to a type
Console.WriteLine(((String)null).IsDefault());
}
}
// The type cannot be generic
public static class TypeHelper
{
// I made the method generic instead
public static bool IsDefault<T>(this T val)
{
return EqualityComparer<T>.Default.Equals(val, default(T));
}
}
To handle all types of T, including where T is a primitive type, you'll need to compile in both methods of comparison:
T Get<T>(Func<T> createObject)
{
T obj = createObject();
if (obj == null || obj.Equals(default(T)))
return obj;
// .. do a bunch of stuff
return obj;
}
Extension method based on accepted answer.
public static bool IsDefault<T>(this T inObj)
{
return EqualityComparer<T>.Default.Equals(inObj, default);
}
Usage:
private bool SomeMethod(){
var tValue = GetMyObject<MyObjectType>();
if (tValue == null || tValue.IsDefault()) return false;
}
Alternate with null to simplify:
public static bool IsNullOrDefault<T>(this T inObj)
{
if (inObj == null) return true;
return EqualityComparer<T>.Default.Equals(inObj, default);
}
Usage:
private bool SomeMethod(){
var tValue = GetMyObject<MyObjectType>();
if (tValue.IsNullOrDefault()) return false;
}
There is going to be a problem here -
If you're going to allow this to work for any type, default(T) will always be null for reference types, and 0 (or struct full of 0) for value types.
This is probably not the behavior you're after, though. If you want this to work in a generic way, you probably need to use reflection to check the type of T, and handle value types different than reference types.
Alternatively, you could put an interface constraint on this, and the interface could provide a way to check against the default of the class/struct.
I think you probably need to split this logic into two parts and check for null first.
public static bool IsNullOrEmpty<T>(T value)
{
if (IsNull(value))
{
return true;
}
if (value is string)
{
return string.IsNullOrEmpty(value as string);
}
return value.Equals(default(T));
}
public static bool IsNull<T>(T value)
{
if (value is ValueType)
{
return false;
}
return null == (object)value;
}
In the IsNull method, we're relying on the fact that ValueType objects can't be null by definition so if value happens to be a class which derives from ValueType, we already know it's not null. On the other hand, if it's not a value type then we can just compare value cast to an object against null. We could avoid the check against ValueType by going straight to a cast to object, but that would mean that a value type would get boxed which is something we probably want to avoid since it implies that a new object is created on the heap.
In the IsNullOrEmpty method, we're checking for the special case of a string. For all other types, we're comparing the value (which already know is not null) against it's default value which for all reference types is null and for value types is usually some form of zero (if they're integral).
Using these methods, the following code behaves as you might expect:
class Program
{
public class MyClass
{
public string MyString { get; set; }
}
static void Main()
{
int i1 = 1; Test("i1", i1); // False
int i2 = 0; Test("i2", i2); // True
int? i3 = 2; Test("i3", i3); // False
int? i4 = null; Test("i4", i4); // True
Console.WriteLine();
string s1 = "hello"; Test("s1", s1); // False
string s2 = null; Test("s2", s2); // True
string s3 = string.Empty; Test("s3", s3); // True
string s4 = ""; Test("s4", s4); // True
Console.WriteLine();
MyClass mc1 = new MyClass(); Test("mc1", mc1); // False
MyClass mc2 = null; Test("mc2", mc2); // True
}
public static void Test<T>(string fieldName, T field)
{
Console.WriteLine(fieldName + ": " + IsNullOrEmpty(field));
}
// public static bool IsNullOrEmpty<T>(T value) ...
// public static bool IsNull<T>(T value) ...
}
I use:
public class MyClass<T>
{
private bool IsNull()
{
var nullable = Nullable.GetUnderlyingType(typeof(T)) != null;
return nullable ? EqualityComparer<T>.Default.Equals(Value, default(T)) : false;
}
}
Just a hacky answer and as a reminder for myself.
But I find this quite helpful for my project.
The reason I write it like this is that because I don't want default integer 0 being marked as null if the value is 0
private static int o;
public static void Main()
{
//output: IsNull = False -> IsDefault = True
Console.WriteLine( "IsNull = " + IsNull( o ) + " -> IsDefault = " + IsDefault(o));
}
public static bool IsNull<T>(T paramValue)
{
if( string.IsNullOrEmpty(paramValue + "" ))
return true;
return false;
}
public static bool IsDefault<T>(T val)
{
return EqualityComparer<T>.Default.Equals(val, default(T));
}
Don't know if this works with your requirements or not, but you could constrain T to be a Type that implements an interface such as IComparable and then use the ComparesTo() method from that interface (which IIRC supports/handles nulls) like this:
public void MyMethod<T>(T myArgument) where T : IComparable
...
if (0 == myArgument.ComparesTo(default(T)))
There are probably other interfaces that you could use as well IEquitable, etc.
#ilitirit:
public class Class<T> where T : IComparable
{
public T Value { get; set; }
public void MyMethod(T val)
{
if (Value == val)
return;
}
}
Operator '==' cannot be applied to operands of type 'T' and 'T'
I can't think of a way to do this without the explicit null test followed by invoking the Equals method or object.Equals as suggested above.
You can devise a solution using System.Comparison but really that's going to end up with way more lines of code and increase complexity substantially.
I think you were close.
if (myArgument.Equals(default(T)))
Now this compiles, but will fail if myArgument is null, which is part of what I'm testing for. I can add an explicit null check like this:
You just need to reverse the object on which the equals is being called for an elegant null-safe approach.
default(T).Equals(myArgument);