How does GetValueOrDefault work?
Matthew Harrington
I'm responsible for a LINQ provider which performs some runtime evaluation of C# code. As an example:
int? thing = null;
accessor.Product.Where(p => p.anInt == thing.GetValueOrDefault(-1))Currently the above code doesn't work with my LINQ provider due to thing being null.
While I've been working with C# for a long time, I don't know how GetValueOrDefault is implemented and therefore how I should resolve this.
So my question is: how does GetValueOrDefault work in the case that the instance on which it is called is null? Why isn't a NullReferenceException thrown?
A follow on question: how should I go about replicating a call to GetValueOrDefault using reflection, given that I need to handle null values.
5 Answers
thing isn't null. Since structs can't be null, so Nullable<int> can't be null.
The thing is... it is just compiler magic. You think it is null. In fact, the HasValue is just set to false.
If you call GetValueOrDefault it checks if HasValue is true or false:
public T GetValueOrDefault(T defaultValue)
{ return HasValue ? value : defaultValue;
} 5 GetValueOrDefault () prevents errors that may occur because of null. Returns 0 if the incoming data is null.
int ageValue = age.GetValueOrDefault(); // if age==null
The value of ageValue will be zero.
A NullReferenceException isn't thrown, because there is no reference. The GetValueOrDefault is a method in the Nullable<T> structure, so what you use it on is a value type, not a reference type.
The GetValueOrDefault(T) method is simply implemented like this:
public T GetValueOrDefault(T defaultValue) { return HasValue ? value : defaultValue;
}So, to replicate the behaviour you just have to check the HasValue property to see what value to use.
Hi GetValueOrDefault() has been in c# for some time now.
Guid? nullableGuid = null;
Guid guid = nullableGuid.GetValueOrDefault() 1 I think you provider was not working correctly. I've made a simple test and it worked correctly.
using System;
using System.Linq;
namespace ConsoleApp4
{ class Program { static void Main(string[] args) { var products = new Product[] { new Product(){ Name = "Product 1", Quantity = 1 }, new Product(){ Name = "Product 2", Quantity = 2 }, new Product(){ Name = "Product -1", Quantity = -1 }, new Product(){ Name = "Product 3", Quantity = 3 }, new Product(){ Name = "Product 4", Quantity = 4 } }; int? myInt = null; foreach (var prod in products.Where(p => p.Quantity == myInt.GetValueOrDefault(-1))) { Console.WriteLine($"{prod.Name} - {prod.Quantity}"); } Console.ReadKey(); } } public class Product { public string Name { get; set; } public int Quantity { get; set; } }
}It produces as output: Product -1 - -1
3