【问题标题】:Creating a Generic Dictionary From a Generic List从通用列表创建通用字典
【发布时间】:2010-03-03 08:46:04
【问题描述】:

我正在尝试执行以下操作,但我认为我一定遗漏了一些东西......(对泛型来说相当新)

(需要针对.NET 2.0 BTW)

interface IHasKey
{
    string LookupKey { get; set; }
}
...

public static Dictionary<string, T> ConvertToDictionary(IList<T> myList) where T : IHasKey
{
    Dictionary<string, T> dict = new Dictionary<string, T>();
    foreach(T item in myList)
    {
        dict.Add(item.LookupKey, item);
    }

    return dict;
}

不幸的是,这会产生“非泛型声明上不允许使用约束”错误。有什么想法吗?

【问题讨论】:

  • 对不起,我现在把编译器错误信息放在帖子下面了。
  • 你要添加的项目,是同一个类,还是实现了IHasKey的不同类?
  • @Mikael - 是的,课程都不同。

标签: c# generics list dictionary


【解决方案1】:

您尚未声明泛型参数。
将您的声明更改为:

public static Dictionary<string, T> ConvertToDictionary<T> (IList<T> myList) where T : IHasKey{
}

【讨论】:

  • 在这种情况下使用“T where IHasKey”而不是声明 Dictionary 有什么意义?
  • @Mikael:通过这种方式,返回值是 Dictionary 而不是 Dictionary,因此当您访问该值时,您可以避免额外的强制转换并确定哪个您的字典包含的对象。
  • 好点!但是,如果您按照输入列表可能包含 IHasKey 的不同实现的思路来考虑,那么装箱是不可避免的。
  • @Mikael:好的,但请注意,您仍然可以对 T=IHasKey 使用相同的方法。无论如何,我认为通用方法没有缺点。
  • 我同意 :) 所以它转移到一个哲学问题:你是否应该笼统地定义它,当你知道你将使用接口而不是具体类型来实例化它时?
【解决方案2】:

试试这样的

public class MyObject : IHasKey
{
    public string LookupKey { get; set; }
}

public interface IHasKey
{
    string LookupKey { get; set; }
} 


public static Dictionary<string, T> ConvertToDictionary<T>(IList<T> myList) where T: IHasKey 
{ 
    Dictionary<string, T> dict = new Dictionary<string, T>(); 
    foreach(T item in myList) 
    { 
        dict.Add(item.LookupKey, item); 
    } 
    return dict; 
}

List<MyObject> list = new List<MyObject>();
MyObject o = new MyObject();
o.LookupKey = "TADA";
list.Add(o);
Dictionary<string, MyObject> dict = ConvertToDictionary(list);

您忘记了方法中的通用参数

public static Dictionary<string, T> ConvertToDictionary<T>(IList<T> myList) where T: IHasKey

【讨论】:

    【解决方案3】:

    由于输入列表中的类不同(正如您在评论中所说),您可以按照@orsogufo 的建议实现它,或者您也可以在接口本身上实现您的签名:

    public static Dictionary<string, IHasKey> ConvertToDictionary(IList<IHasKey> myList) 
    {
        var dict = new Dictionary<string, IHasKey>();
        foreach (IHasKey item in myList)
        {
            dict.Add(item.LookUpKey, item);
        }
        return dict;
    }
    

    如果您有其他答案的 cmets 中所述的接口的一个特定实现的列表,则最好使用通用声明。

    【讨论】:

    • 是的,但正如 orsogufo 指出的那样,这需要转换 IHasKey 对象以在从字典中检索后访问其他成员。
    • 但是如果输入列表是 IList 类型,我认为这是因为你有不同的类,你使用哪个实现没有区别,因为你会得到一个额外的装箱如果你想对特定的班级做点什么。
    • 输入列表不一定是 IList 但如果是你就对了
    • @Mikael,输入列表可以是 IList,其中 Customer : IHasKey。在这种情况下,我们会返回 Dictionary 而不是 Dictionary。客户重视的字典更有用(避免不必要的转换)。
    • @David B:在 List 有一个类类型的情况下,我 100% 同意,但@Damien 在评论中说该列表可能包含 IHasKey 的多个实现(我理解的方式),在这种情况下,它必须是 IList。只是想了解@Damien 想要涵盖的实际场景。
    猜你喜欢
    • 2017-03-25
    • 1970-01-01
    • 2021-01-26
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2018-12-17
    相关资源
    最近更新 更多