【问题标题】:Collection of key-value pairs where only key type is known只知道键类型的键值对集合
【发布时间】:2015-06-05 10:58:30
【问题描述】:

我想要一个键值对集合类,其中不知道实例化级别的键类型,但只知道向集合添加新元素时的值类型。

考虑下面的代码sn-p

public class Collection<TKey> where TKey : class
{
    public ICollection<KeyValuePair<TKey, IValue>> Col { get; set; }

    public void Add<TValue>(TKey key, TValue value) where TValue : IValue
    {
        Col.Add(new KeyValuePair<TKey, IValue>(key, value));
    }
}

public interface IValue
{
}

这很好用,但是,上面代码的问题是插入类型必须是 IValue 类型,因为原语不是 IValue 的实现者,它们不能被添加到列表中。

我不能使用object 代替TValue / IValue

编辑

我想使用任何!键值对的 value 参数的类型。如果可能的话,我想摆脱IValue。这是我可以编译代码的唯一方法

理想用法示例如下:

    collection.Add("hello", 10);
    collection.Add("peter", "temp");
    collection.Add("hello1", new Foo());
    collection.Add("hello2", new Bar());

编辑 我不能使用对象,因为对象并非所有对象都是可串行化的,但是,我将实现更改为

class Program
{
    static void Main(string[] args)
    {
        var collection = new Collection<string>();
        collection.Add("hello", 10);
        collection.Add("peter", "temp");
        collection.Add("hello", new Bar());
    }
}

[Serializable]
public class KeyValuePair<TKey, TValue>
{
    private TKey _key;
    private TValue _value;

    public KeyValuePair(TKey key, TValue value)
    {
        _key = key;
        _value = value;
    }

    public TKey Key
    {
        get { return _key; }
        set { _key = value; }
    }

    public TValue Value
    {
        get { return _value; }
        set { _value = value; }
    }
}

public class Collection<TKey> where TKey : class
{
    public ICollection<KeyValuePair<TKey, ISerializable>> Col { get; set; }

    public void Add<TValue>(TKey key, TValue value) where TValue : ISerializable
    {
        Col.Add(new KeyValuePair<TKey, TValue>(key, value));
    }
}

编译器说argument type &lt;TKey, TValue&gt; is not assignable to parameter type &lt;TKey, ISerializable&gt;

【问题讨论】:

  • 您有相互冲突的要求。您说的是要添加到仅允许类型实现 IValue 的集合中的“原语”(值类型?)。
  • 你能解释一下为什么不能使用对象吗?
  • 为什么不能用 IValue 扩展原语并使用扩展类?
  • @CodeCaster 你误会了。我只添加了 Ivalue 以便我可以编译代码。 keyValue 类需要两种类型,而 Collection 类只定义了一种泛型类型。如果我能摆脱IValue,那就太好了
  • @Jegan - 我可以写一个包装类......但我觉得这更像是一个黑客

标签: c# generics icollection keyvaluepair


【解决方案1】:

事先注意:作为个人喜好,当我需要重复的键输入时,我倾向于使用字典来存储具有唯一键的键/值对或多映射/ilookup。


如果您使用 C# 3.5 或更早版本,则可以使用

var dic = new Dictionary<string, object>();  

假设您使用的是 C# 4,您可以使用

var dic = new Dictionary<string, dynamic>();  

例如,人们喜欢用它来存储 JSON 数据。


你可以用 Rx-Linq 做很多事情,但我想指出你可以写:

var dic = new Dictionary<string, Lazy<string>>();

您可以在其中存储生成字符串的脚本。

【讨论】:

    【解决方案2】:

    如果您希望您的值包含原始类型,例如 int、float 等和自定义类型,那么您应该使用 object 而不是 IValue。

    public class Collection<TKey> where TKey : class
    {
        public ICollection<KeyValuePair<TKey, object>> Col { get; set; }
    
        public void Add(TKey key, object value)
        {
            Col.Add(new KeyValuePair<TKey, object>(key, value));
        }
    }
    

    此外,如果您想在运行时快速查找基于哈希的键,您可能希望将 ICollection&lt;...&gt; 更改为简单的 Dictionary&lt;TKey, object&gt;

    【讨论】:

    • 附带说明:这将大量使用拳击并且可能是性能问题。
    • 这是显而易见的答案,但 OP 说 “我不能使用对象代替 TValue / IValue”。除非很清楚为什么不这样做,否则我不会回答显而易见的问题。
    猜你喜欢
    • 2018-03-15
    • 1970-01-01
    • 2017-04-20
    • 2021-01-18
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    相关资源
    最近更新 更多