我目前正在重写自定义RPC机制的一部分(不能被其他东西替换,所以不要建议;-))。调用的参数收集在内部使用字典的自定义集合中。有一个方法T Get<T>(string)
来检索命名参数。对于可选参数,我想添加一个返回参数的TryGet<T>(string)
方法,如果它不存在则添加null
,这样调用代码可以使用null合并运算符提供默认值。当然,对于值类型,这不起作用,但我可以使用T?
代替,这就是我想要的。
所以我拥有的是:
public class Arguments
{
// lots of other code here
public T TryGet<T>(string argumentName) where T : class
{
// look up and return value or null if not found
}
public T? TryGet<T>(string argumentName) where T : struct
{
// look up and return value or null if not found
}
}
有了这个,我希望能够做到以下几点:
return new SomeObject(
args.TryGet<string>("Name") ?? "NoName",
args.TryGet<int>("Index") ?? 1
);
由于约束是互斥的,编译器应该能够生成正确的代码(总是可以从调用站点给出的泛型类型推断出调用)。编译器抱怨该类型已经定义了一个名为“TryGet”的成员,其参数类型相同。
有没有办法在不给两种方法赋予不同名称的情况下制作类似这样的作品?
答案 0 :(得分:5)
.NET Framework中处理此方案的类的方式是TryGetValue
,其out
参数。返回值表示get是否成功,out
参数包含请求的值(成功时)或合适的默认值(失败时)。
此模式使得实现对于引用和值类型非常简单。您只需要一种方法来处理这两种情况。
有关此模式的示例,请参阅Dictionary<TKey,TValue>.TryGetValue
。
答案 1 :(得分:5)
Constraints are not part of the signature.因此,您的问题的答案是否。
答案 2 :(得分:3)
这不起作用的原因是因为你不能有两个具有相同名称和相同参数类型的方法(方法重载不考虑返回类型)。相反,您可以定义一个没有通用约束的方法,该约束适用于值和引用类型:
public T TryGet<T>(string argumentName)
{
if (!_internalDictionary.ContainsKey(argumentName))
{
return default(T);
}
return (T)_internalDictionary[argumentName];
}
答案 3 :(得分:3)
另一种解决方案可能就是这个:
public class Arguments {
public T Get<T>(string argumentName,T defaultValue) {
// look up and return value or defaultValue if not found
}
}
return new SomeObject(
args.Get<string>("Name","NoName"),
args.Get<int>("Index",1)
);
在这种特殊情况下,您甚至不必指定泛型类型,因为它可以通过默认参数推断:
return new SomeObject(
args.Get("Name","NoName"),
args.Get("Index",1)
);