Возвращает ноль, если словарь с ненулевыми значениями не соответствует - PullRequest
1 голос
/ 19 апреля 2020

У меня есть словарь со значением типа integer. Когда я заполняю свой класс одним из свойств типа Nullable<int>, я хочу заполнить это свойство значением из словаря на основе заданного идентификатора продукта.

Как я могу получить обнуляемый тип, когда нет соответствующие значения для данного идентификатора продукта?

public class OrderLine
{
    public int? AvailableQuantity { get; set; }
}

var selectedProductId = Guid.NewGuid();
var products = new Dictionary<Guid, int>
{
    { Guid.NewGuid(), 1 },
    { Guid.NewGuid(), 2 },
    { Guid.NewGuid(), 3 },
};

var result = new OrderLine
{
    Id = Guid.NewGuid(),
    ProductId = selectedProductId,
    AvailableQuantity = products.GetValueOrDefault(selectedProductId, default)
};

Подход, приведенный выше, возвращает 0 вместо null

И компилятор не может скомпилироваться при попытке

AvailableQuantity = products.GetValueOrDefault(selectedProductId, default(int?))

Аргументы типа для метода 'TValue System.Collections.Generi c .CollectionExtensions.GetValueOrDefault (this IReadOnlyDictionary, TKey, TValue)' не могут быть выведены из использования. Попробуйте явно указать аргументы типа.

Я не могу изменить тип словаря. Словарь - это возвращаемый тип широко используемого метода. Это первый случай, когда нам нужно разобраться со сценарием, в котором идентификатор продукта не может быть в этом словаре.

Я бы не хотел перечислять словарь, чтобы изменить его тип на nullable

Ответы [ 4 ]

4 голосов
/ 19 апреля 2020

Вы можете написать C# Расширения, которые используют TryGetValue

Например,

public static class DictionaryExtensions
{
    public static TValue? GetValueOrNull<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
        where TValue : struct
    {
        if (dict.TryGetValue(key, out TValue value))
        {
            return value;
        }

        return null;
    }
}

Использование:

products.GetValueOrNull(selectedProductId);

PS: Это расширение также работает для других типов, кроме int, например, decimal, bool и других структурных типов

1 голос
/ 19 апреля 2020

Если вы делаете это только один раз - используйте троичный оператор

Quantity = products.TryGetValue(productId, out var qty) ? qty : default(int?)

Если вы собираетесь делать это в нескольких местах, оберните код выше в метод расширения

0 голосов
/ 19 апреля 2020

Пожалуйста, попробуйте

var products = new Dictionary<Guid, int?>
{
{ Guid.NewGuid(), 1 },
{ Guid.NewGuid(), 2 },
{ Guid.NewGuid(), 3 },
};
0 голосов
/ 19 апреля 2020

Вы получаете значение по умолчанию 0, потому что это значение по умолчанию int (не обнуляемое).

Чтобы получить значение по умолчанию null, измените тип значения в словаре на int? (обнуляемый):

var products = new Dictionary<Guid, int?>
{
    { Guid.NewGuid(), 1 },
    { Guid.NewGuid(), 2 },
    { Guid.NewGuid(), 3 },
};
...