C# 为未知类型返回空值
我正在尝试使用泛型编写以下方法。(我的实际方法比这更复杂。)C# 为未知类型返回空值,c#,generics,dictionary,null,nullable,C#,Generics,Dictionary,Null,Nullable,我正在尝试使用泛型编写以下方法。(我的实际方法比这更复杂。) public T ParseDictionaryItem(字符串s,字典) { T结果; if(dictionary.TryGetValue(s,out结果)) 返回结果; //TODO:返回特殊值,如null,以指示无效项 } 我的目标是,如果项目不在字典中,则返回类似于null的内容 问题是我不知道t是什么类型。例如,如果T是一个整数,那么我应该返回类型T?。但是,如果T是一个类,那么它已经可以为空。直到运行时我才知道这一点 任
public T ParseDictionaryItem(字符串s,字典)
{
T结果;
if(dictionary.TryGetValue(s,out结果))
返回结果;
//TODO:返回特殊值,如null,以指示无效项
}
我的目标是,如果项目不在字典中,则返回类似于null的内容
问题是我不知道t
是什么类型。例如,如果T
是一个整数,那么我应该返回类型T?
。但是,如果T
是一个类,那么它已经可以为空。直到运行时我才知道这一点
任何人都能找到一种干净的方法来返回此方法中的特殊值,以指示该项无效吗?我愿意返回除null
以外的内容,但它必须是一个特殊值。(0不是整数的特殊值。)我建议返回一个ParseResult
,它的定义如下:
public struct ParseResult<T>
{
// Or an exception, or a way of creating an exception
private readonly bool success;
private readonly T value;
// Accessors etc
}
public结构解析结果
{
//或异常,或创建异常的方法
私人只读bool成功;
私有只读T值;
//访问者等
}
这样,您就不必担心可空性,并且可以非常清楚地说明您正在做什么。这是我使用过的模式,在我看来,它非常有效。(目前我们使用的是类而不是结构,但我可能会改变这一点…)
与其他方法相比,我更喜欢它,因为:
- 调用它是干净的,不像使用
out
参数
- 它不需要丑陋且可能昂贵的try/catch处理
- 无论
T
是引用类型还是值类型,其行为方式都完全相同
- 它足够灵活,可以表示
null
是成功解析值的情况
- 您仍然可以传播失败的原因,而不必在不需要时抛出异常
您可以创建两种方法,一种用于值类型,另一种用于引用类型。
值类型方法将返回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;
}
公共电话?ParseDictionaryItemValueType(字符串s,字典字典)
其中T:struct
{
T结果;
if(dictionary.TryGetValue(s,out结果))
返回结果;
返回null;
}
public T ParseDictionaryItemReferenceType(字符串s,字典字典)
T:在哪里上课
{
T结果;
TryGetValue(s,输出结果);
返回结果;
}
也许两个重载会有所帮助:
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);
}
公共电话?ParseStructDictionaryItem(字符串s,字典字典),其中T:struct
{
T结果;
if(dictionary.TryGetValue(s,out结果))
返回结果;
返回null;
}
公共T ParseReferenceDictionaryItem(字符串s,字典),其中T:class
{
T结果;
if(dictionary.TryGetValue(s,out结果))
返回结果;
返回默认值(T);
}
为什么要重新发明轮子?看看您自己的代码:
您正在使用字典的
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 bool tryparsedictionary项(字符串s、字典字典、out T结果)
{
if(dictionary.TryGetValue(s,out结果)){
返回true;
}
返回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;
}
public T tryparsedictionary项(字符串s、字典、输出成功)
{
T结果=默认值(T);
成功=(dictionary.TryGetValue(s,out结果))
返回结果;
}
最好的方法是default(T)
,但这对于int
来说并不是“唯一的”。最简单的方法是创建两个重载—一个用于类类型,另一个用于可空结构。或者创建您自己的或者
键入并返回该值。为什么调用方不直接使用TryGetValue?它返回一个bool,指示该项是否有效,如果有效,则out参数包含该项。或者,如果方法更复杂,至少是遵循这种模式的东西。@mikez:正如我在问题中指出的,我的实际方法比这个更复杂。我简化了它来说明我的问题。谢谢,我正在考虑返回一个包含更多信息的类,但希望得到更轻松、更简单的内容。但这也许是最好的方法。我发现自己越来越多地使用这种模式。如果Nullable
没有泛型参数是值类型的约束…@Jon:我能问一下,为什么在这里选择struct
而不是类吗?@JonathanWood:很难说,没错,特别是考虑到这与野田佳彦时代的决定相反。它感觉有点像Nullable
,实际上只是装饰了一个“真实”值。避免在每个解析操作上分配heal也很好。“当然,它也适用于类。”AnthonyPegram我知道,它们有不同的名称。对不起,我刚刚注意到了这一点。继续。是的,我看到了,但我真的不喜欢那种方法。首先,out
参数不能是类实例属性。我觉得这更尴尬。
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;
}