返回未知类型的空值

时间:2015-05-14 14:29:59

标签: c# generics dictionary null nullable

我正在尝试使用泛型编写以下方法。 (我的实际方法比这更复杂。)

public T ParseDictionaryItem<T>(string s, Dictionary<string, T> dictionary)
{
    T result;
    if (dictionary.TryGetValue(s, out result))
        return result;
    // TODO: Return special value such as null to indicate invalid item
}

如果项目不在词典中,我的目标是返回null之类的内容。

问题是我不知道T是什么类型。例如,如果T是一个整数,那么我应该返回类型T?。但是,如果T是一个类,那么它已经可以为空了。直到运行时我才会知道这一点。

任何人都可以看到一种干净的方法来返回此方法中的特殊值以指示该项无效吗?我愿意返回null之外的其他内容,但它必须是一个特殊值。 (0不是整数的特殊值。)

4 个答案:

答案 0 :(得分:11)

我建议返回ParseResult<T>,其定义如下:

public struct ParseResult<T>
{
    // Or an exception, or a way of creating an exception
    private readonly bool success;
    private readonly T value;

    // Accessors etc
}

这样你就不必担心可空性,而且你可以非常清楚你正在做什么。这是我在Noda Time中使用的模式,在我看来它的效果非常好。 (目前我们使用的是类而不是结构,但我可能会改变它......)

我更喜欢其他方法,因为:

  • 与使用out参数
  • 不同,呼叫干净
  • 它不需要丑陋且可能很昂贵的尝试/捕获处理
  • 无论T是引用类型还是值类型
  • ,它的行为完全
  • 它足够灵活,可以代表null 成功解析价值的情况
  • 当您不需要时,您仍然可以传播失败的原因而不会抛出异常

答案 1 :(得分:5)

也许两个重载会有所帮助:

public T? ParseStructDictionaryItem<T>(string s, Dictionary<string, T> dictionary) where T : struct
{
    T result;
    if (dictionary.TryGetValue(s, out result))
        return result;
    return null;
}

public T ParseReferenceDictionaryItem<T>(string s, Dictionary<string, T> dictionary) where T : class
{
    T result;
    if (dictionary.TryGetValue(s, out result))
        return result;
    return default(T);
}

答案 2 :(得分:4)

您可以为值类型创建两个方法,为引用类型创建另一个方法。 值类型方法将返回T?而不是T。在这两种方法中,您都可以返回null来表示无效值。

public T? ParseDictionaryItemValueType<T>(string s, Dictionary<string, T> dictionary)
 where T : struct
{
    T result;
    if (dictionary.TryGetValue(s, out result))
        return result;
    return null;
}

public T ParseDictionaryItemReferenceType<T>(string s, Dictionary<string, T> dictionary)
 where T : class
{
    T result;
    dictionary.TryGetValue(s, out result);
    return result;
}

答案 3 :(得分:0)

为什么重新发明轮子?看看你自己的代码:
您正在使用Dictionary的TryGetValue方法。它如何处理同样的问题?
我建议你跟随.Net Framework开发人员的脚步并做同样的事情:

public bool TryParseDictionaryItem<T>(string s, Dictionary<string, T> dictionary, out T result)
{
   if (dictionary.TryGetValue(s, out result)) {
       return true;
   }
   return false;

}

<强>更新
既然你不喜欢这种方法,那怎么样就把它转过头来?

public T TryParseDictionaryItem<T>(string s, Dictionary<string, T> dictionary, out bool Success)
{
   T result = default(T);
   Success = (dictionary.TryGetValue(s, out result)) 
   return result;
}