在编译时检查Dictionary.Add()键的唯一性

时间:2014-09-12 13:03:09

标签: c#

使用Add()方法添加字典时,是否可以在编译时检查字典在方法范围内的键唯一性?

示例:有许多支付解决方案提供商(PayPal,PayEx等)在您查询事务时提供某种状态结果,假设为整数。由于每个PSP处理不同的状态,我们都有固定数量的系统状态(例如Pending,Aborted,Committed等),这些状态映射到每个PSP的各种状态代码。

public static class ResponseMapping
{
    private static readonly Dictionary<int, PaymentResult> ResultMap;

    static ResponseMapping()
    {
        ResultMap = new Dictionary<int, PaymentResult>();

        ResultMap.Add(1, PaymentResult.LogonError);
        ResultMap.Add(2, PaymentResult.Pending);
        ResultMap.Add(9, PaymentResult.Ok);

        // OH DEAR, THIS WILL BLOW UP
        ResultMap.Add(1, PaymentResult.Something);
    }

    public static PaymentResult FindAppropriateResponse(int resultCode)
    {
        if (ResultMap.ContainsKey(resultCode))
        {
            return ResultMap[resultCode];
        }

        return PaymentResult.UnknownResult;
    }
}

一个简单的快捷方式是使用[]索引表示法来添加每个地图,但使用Add(),您可以避免覆盖您并不意味着的内容。

不幸的是,这种方式在运行时爆炸了。有没有一种技术可以让它在编译时爆炸?

6 个答案:

答案 0 :(得分:4)

我认为你不能在编译时检查密钥是否存在。相反,您可以使用Dictionary.ContainsKey方法,例如:

int key = 1; //your key
if(!ResultMap.ContainsKey(key))
{
    ResultMap.Add(key, PaymentResult.Something);
}

答案 1 :(得分:1)

您可以使用ContainsKey

if(!ResultMap.ContainsKey(1))
{
    ResultMap.Add(1, PaymentResult.Something);
}

TryGetValue

obj item;
if(!ResultMap.TryGetValue(1, out item))
    ResultMap.Add(1, PaymentResult.Something);

答案 2 :(得分:1)

如果你真的需要一个字典对象,我认为你不能在编译时这样做,并且可以通过单元测试来伪装它。但如果您只是想要查看,请使用开关。

public static PaymentResult FindAppropriateResponse(int resultCode)
{
    switch(resultCode)
    {
         case 1:
            return PaymentResult.LogonError;
         case 2:
            return PaymentResult.Pending;
         case 3:
             return PaymentResult.Ok;
         default:
             return PaymentResult.UnknownResult;
         case 1: // Does blow up at compile time
             return PaymentResult.Something;
    }
}

答案 3 :(得分:0)

您可以定义一个使用的方法而不是Add。 它将添加值(如果不存在)或替换它(如果存在)。

private void Add(Dictionary<int, PaymentResult> PaymentResults, int index, PaymentResult pResult)
{
    if(PaymentResults.ContainsKey(index))
    {
        PaymentResults[index] = pResult;
    }
    else
    {
        PaymentResults.Add(index, pResult);
    }
}

并使用它

this.Add(ResultMap, 1, PaymentResult.LogonError);

答案 4 :(得分:0)

这是相关但不完全相关的。我遇到的问题是我不确定是否存在密钥,所以我创建了一个简单的方法。

    private void AddKey(string key, string value)
    {
        if (!Dictionary.ContainsKey(key))
               Dictionary.Add(key, value);
    }

刚刚调用AddKey(键,值);

也许这会对你有所帮助。

答案 5 :(得分:0)

或延伸

public static class Extensions
{
    public static bool Push<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
    {
        try
        {
            if (dictionary.ContainsKey(key))
            {
                dictionary[key] = value;
            }
            else
            {
                dictionary.Add(key, value);
            }
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    public static TValue Pull<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
    {
        try
        {
            return dictionary.ContainsKey(key) ? dictionary[key] : default(TValue);
        }
        catch (Exception ex)
        {
            return default(TValue);
        }
    }
}

然后你可以做

    ResultMap = new Dictionary<int, PaymentResult>();

    ResultMap.Push(1, PaymentResult.LogonError); //1 -> PaymentResult.LogonError
    ResultMap.Push(1, PaymentResult.Something); //1 -> PaymentResult.Something