C# 使用泛型重构

C# 使用泛型重构,c#,.net,generics,C#,.net,Generics,我有一个简单的方法接口,比如 bool TryGetValue(string key, out string value); bool TryGetValue(string key, out int value); bool TryGetValue(string key, out double value); bool TryGetValue(string key, out DateTime value); // only value types

我有一个简单的方法接口,比如

     bool TryGetValue(string key, out string value);
     bool TryGetValue(string key, out int value);
     bool TryGetValue(string key, out double value);
     bool TryGetValue(string key, out DateTime value);
     // only value types allowed 

     //with the implementation based on dictionary<string, object> 
     bool TryGetValue(string key, out string value)
     {
        object rc;
        if ( dict.TryGetValue(key, out rc) )
        {
            value = rc.ToString();
            return true;
        }

        value = null;
        return false;
     }
bool TryGetValue(字符串键,输出字符串值);
bool TryGetValue(字符串键,out int值);
bool TryGetValue(字符串键,输出双精度值);
bool TryGetValue(字符串键,out DateTime值);
//仅允许值类型
//基于字典的实现
bool TryGetValue(字符串键,输出字符串值)
{
对象rc;
if(dict.TryGetValue(键,输出rc))
{
value=rc.ToString();
返回true;
}
值=空;
返回false;
}
看起来像是泛型的完美例子

     bool TryGetValue<T>(string key, out T value) where T: ValueType;
bool TryGetValue(字符串键,out T值),其中T:ValueType;
除了无法实现func之外,还有人吗

更新-以下内容未编译,我希望避免创建多个TryGet。。。芬克斯

     bool TryGetValue<T>(string key, out T value)
     {
         return dict.TryGetValue(key, out value) ;
     }
bool TryGetValue(字符串键,out T值)
{
返回dict.TryGetValue(键,输出值);
}
试试这个:

public bool TryGetValue<T>(string key, out T value) where T : struct
{
  object obj;
  var result = dict.TryGetValue(key, out obj);
  value = (T)obj;
  return result;
}
public bool TryGetValue(字符串键,out T值),其中T:struct
{
对象对象对象;
var结果=dict.TryGetValue(输入,输出obj);
值=(T)obj;
返回结果;
}

它并不漂亮,但处理了
out
的局限性……也许有人可以把它缩短得更短?如果是这样的话,请评论……随时学习新方法。

看看:它可能会对你有用。还有,为什么不扩展字典呢?

我猜您想要的是:

 bool TryGetValue<TValue>(string key, out TValue value)
 {
    object rc;
    if (dict.TryGetValue(key, out rc))
    {
        value = (TValue)rc;
        return true;
    }

    value = default(TValue);
    return false;
 }

注意-JaredPar得到了第一个答案,但似乎已经删除了他的答案,所以我取消删除我的答案,因为我认为这是OP想要的。对于任何意外的复制,我深表歉意。

我相信Aaronaught已经抓住了问题的主要症结所在(捕获
对象
并向
T
强制转换/取消绑定),但还有一些额外的要点:

  • 要限制值类型(*),请使用
    where T:struct
    ,而不是
    where T:ValueType
  • …但请注意,
    string
    不是值类型,因此这可能不是一个好的“适合”
  • …和(*=)注意,
    其中T:struct
    也排除了
    可为空的

因此,我认为您只需要完全删除该约束。

我可能会选择这样的约束,尽管正如Marc指出的那样,
struct
约束不允许使用字符串:

private static class Container<T> where T : struct
{
    public static Dictionary<string, T> Dict = new Dictionary<string, T>();
}

public bool TryGetValue<T>(string key, out T value) where T : struct
{
    return Container<T>.Dict.TryGetValue(key, out value);
}
私有静态类容器,其中T:struct
{
公共静态字典Dict=新字典();
}
公共bool TryGetValue(字符串键,out T值),其中T:struct
{
返回Container.Dict.TryGetValue(key,out值);
}

扩展方法。

namespace AssemblyCSharp
{
    public static class ExtentionMethod {

        public static bool TryGetValue<T, T2>(this Dictionary<T, T2> dict, string key, out T value) {
            return dict.TryGetValue(key, out value);
        }
    }
}
namespace assemblycharp
{
公共静态类扩展方法{
公共静态bool TryGetValue(此字典dict dict、字符串键、out T值){
返回dict.TryGetValue(键,输出值);
}
}
}

业务规则-只能是基本值类型嗯,请原谅我的这一点,但基本值类型是什么?这就是msdn对值类型(结构/枚举)的说明,用户定义就是其中之一。如果存在与键关联的对象,但类型错误,则最好返回
false
,而不是抛出InvalidCastException。@Anon:我可以从两个方面看到它。如果您返回
false
,则字典在欺骗您;它说它没有钥匙,但它真的有。如果您有一个典型的
If(!lookup.TryGetValue(key,out value)){lookup.Add(key,newValue)}
,那么它将意外失败。这取决于这个类将如何使用,不过,我可以看到,在某些情况下,简单地返回
false
将是理想的结果,有没有办法在没有子类化的情况下声明dictionary where T:ValueType?@Kumar:您可以向
TryGetValue
方法添加一个限制来限制输出。您可以将相同的限制添加到
add
方法中(假设存在),以限制进入字典的内容。但如果您正试图创建
字典的实例,则无法创建该实例。即使使用子类化,如果您创建一个
字典,其中T:ValueType
,那么它只能将确切的类型
T
存储为值,您不能将任何旧的
对象
,根据您的问题,这是您需要能够做的。对不起,我不敢相信我编写了
其中T:ValueType
。。。两次!正确的关键字是
struct
,我已经更正了。@Kumar-更新了答案…希望这就是你想要的,如果没有,请告诉我你缺少了什么。
namespace AssemblyCSharp
{
    public static class ExtentionMethod {

        public static bool TryGetValue<T, T2>(this Dictionary<T, T2> dict, string key, out T value) {
            return dict.TryGetValue(key, out value);
        }
    }
}