C# 具有相同名称和参数但结果和约束不同的多个泛型方法

C# 具有相同名称和参数但结果和约束不同的多个泛型方法,c#,generics,constraints,C#,Generics,Constraints,我目前正在重写自定义RPC机制的一部分(它不能被其他东西替代,所以不要建议;-)。调用的参数收集在内部使用字典的自定义集合中。有一个方法T Get(string)用于检索命名参数。对于可选参数,我想添加一个TryGet(string)方法,该方法返回参数,如果参数不存在,则返回null,以便调用代码可以使用null合并运算符提供默认值。当然,对于值类型,这不起作用,但我可以使用t?,这正是我想要的 所以我得到的是: public class Arguments { // lots of

我目前正在重写自定义RPC机制的一部分(它不能被其他东西替代,所以不要建议;-)。调用的参数收集在内部使用字典的自定义集合中。有一个方法
T Get(string)
用于检索命名参数。对于可选参数,我想添加一个
TryGet(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
    }
}
公共类参数
{
//这里还有很多其他的代码
公共T TryGet(字符串参数名),其中T:class
{
//查找并返回值,如果未找到,则返回null
}
公共T?TryGet(字符串参数名),其中T:struct
{
//查找并返回值,如果未找到,则返回null
}
}
因此,我希望能够做到以下几点:

return new SomeObject(
                      args.TryGet<string>("Name") ?? "NoName",
                      args.TryGet<int>("Index") ?? 1
                      );
返回新的SomeObject(
args.TryGet(“名称”)??“NoName”,
参数TryGet(“索引”)??1
);
由于约束是互斥的,编译器应该能够生成正确的代码(始终可以从调用站点上给定的泛型类型推断调用)。编译器抱怨该类型已经使用相同的参数类型定义了一个名为“TryGet”的成员


有没有办法在不给这两个方法不同的名称的情况下使类似的东西起作用?

这不起作用的原因是,不能有两个具有相同名称和相同参数类型的方法(方法重载时不考虑返回类型)。相反,您可以定义一个不带泛型约束的方法,该约束将同时适用于值和引用类型:

public T TryGet<T>(string argumentName)
{
    if (!_internalDictionary.ContainsKey(argumentName))
    {
        return default(T);
    }
    return (T)_internalDictionary[argumentName];
}
publicttryget(字符串参数名)
{
if(!\u internalDictionary.ContainsKey(argumentName))
{
返回默认值(T);
}
return(T)_internalDictionary[argumentName];
}

NET Framework中的类处理此场景的方式是使用
out
参数的
TryGetValue
。返回值指示获取是否成功,其中
out
参数包含请求的值(成功时)或合适的默认值(失败时)

这种模式使得实现对于引用和值类型非常简单。您只需要一个方法来处理这两种情况


有关此模式的示例,请参见。

另一种解决方案可以是:

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)
);

因此,您的问题的答案是否定的。

这不会为值类型提供所需的
null
行为。所需的行为可以通过以下方式实现:
args.TryGet(“Index”)??1
你说得对,乔恩,但是——考虑到达林的评论——至少这是我能想到的最接近我想象的。我想我和我的同事也必须使用代码,他们可以使用一个额外的字符。好主意,但这意味着我无法在线检索我想要的值(如我想如何使用代码的示例所示)。在创建SomeObject之前,我需要声明变量并为每个值调用TryGetValue()。这使得代码比我喜欢的更大,可读性更低。我正在寻找一个更紧凑、更优雅的解决方案。这个看起来不错。不幸的是,乍一看,要知道第二个论点的意思并不那么容易。当然,IntelliSense提供了这些信息,但我希望我的代码易于理解,而不必依赖文档。在我的代码库中有几千行文档注释,我的同事甚至都懒得看这些注释既然代码库已经移到了.NETFramework4,我就可以指定参数名了,比如:args.Get(“name”),defaultValue:“NoName”)。这看起来可读。:-)编译器强迫我回答,但我很高兴也能找到一个解释。谷歌把我带到这里,但不是埃里克的博客。
return new SomeObject(
    args.Get("Name","NoName"),
    args.Get("Index",1)
);