Как работает GetValueOrDefault?
Я отвечаю за поставщика LINQ, который выполняет некоторую оценку кода С# во время выполнения. В качестве примера:
int? thing = null;
accessor.Product.Where(p => p.anInt == thing.GetValueOrDefault(-1))
В настоящее время вышеуказанный код не работает с моим провайдером LINQ из-за того, что thing
имеет значение null.
Пока я работал с С# в течение длительного времени, я не знаю, как реализуется GetValueOrDefault, и поэтому я должен решить эту проблему.
Итак, мой вопрос: как работает GetValueOrDefault
в том случае, если экземпляр, на который он был вызван, равен нулю? Почему не выбрано NullReferenceException
?
А следуйте по вопросу: как мне нужно повторить вызов GetValueOrDefault
с помощью отражения, учитывая, что мне нужно обрабатывать нулевые значения.
Ответы
Ответ 1
thing
не null
. Поскольку structs не может быть null
, поэтому не может Nullable<int>
быть null
.
Дело в том, что это просто магия компилятора. Вы думаете, что это null
. На самом деле, HasValue
просто установлен на false
.
Если вы вызываете GetValueOrDefault
, он проверяет, есть ли HasValue
true
или false
:
public T GetValueOrDefault(T defaultValue)
{
return HasValue ? value : defaultValue;
}
Ответ 2
A NullReferenceException
не выбрасывается, потому что ссылки нет. GetValueOrDefault
- это метод в структуре Nullable<T>
, поэтому вы используете его, это тип значения, а не ссылочный тип.
Метод GetValueOrDefault(T)
просто реализуется следующим образом:
public T GetValueOrDefault(T defaultValue) {
return HasValue ? value : defaultValue;
}
Итак, чтобы воспроизвести поведение, вам просто нужно проверить свойство HasValue
, чтобы узнать, какое значение использовать.
Ответ 3
Я думаю, что ваш провайдер работает неправильно. Я сделал простой тест, и он работал правильно.
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; }
}
}
Он выводит как результат: Продукт -1 - -1