Как работает GetValueOrDefault?

я отвечаю за поставщика LINQ, который выполняет некоторую оценку кода C# во время выполнения. В качестве примера:

int? thing = null;
accessor.Product.Where(p => p.anInt == thing.GetValueOrDefault(-1))

В настоящее время приведенный выше код не работает с моим поставщиком LINQ из-за thing быть null.

пока я работаю с C# в течение длительного времени, я не знаю, как реализован GetValueOrDefault и, следовательно, как я должен это решить.

Итак, мой вопрос: как GetValueOrDefault работа в том случае, если экземпляр, на котором он вызывается имеет значение null? Почему не NullReferenceException кинули?

следовать на вопрос: как я должен пойти о репликации вызова GetValueOrDefault используя отражение, учитывая, что мне нужно обрабатывать нулевые значения.

3 ответов


thing не null. Поскольку структуры не могут быть null, Так что Nullable<int> не может быть null.

вещь... это просто магия компилятора. Вы думаю это null. На самом деле,HasValue расположен в false.

если вы называете GetValueOrDefault он проверяет, если HasValue is true или false:

public T GetValueOrDefault(T defaultValue)
{
    return HasValue ? value : defaultValue;
}

A NullReferenceException не выбрасывается, потому что нет ссылки. The GetValueOrDefault является методом в Nullable<T> structure, поэтому вы используете его для типа значения, а не ссылочного типа.

на GetValueOrDefault(T) метод просто реализуется следующим образом:

public T GetValueOrDefault(T defaultValue) {
    return HasValue ? value : defaultValue;
}

Итак, чтобы воспроизвести поведение, вам просто нужно проверить HasValue свойства, чтобы увидеть, какое значение использовать.


Я думаю, что ваш провайдер работал неправильно. Я сделал простой тест и он правильно работал.

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