【问题标题】:Generic property in class类中的通用属性
【发布时间】:2015-05-18 03:05:57
【问题描述】:

我有一个有 2 个属性 key 和 value 的类,key 将始终用作字符串类型,但是 value 属性的值需要是通用的。

所以我想为属性而不是类创建一个泛型类型,因为如果我为类创建一个泛型,我用于该类的类型将用于所有泛型列表类中的所有项目财产。

谁能告诉我我怎么能做到这一点。下面是类:

   public class KeyValuePairs
    {
        public string Key { get; set; }
        public object Value { get; set; }
    }

【问题讨论】:

  • 你能澄清一下使用KeyValuePair<string, WhaterverTypeYouWant>有什么问题吗?

标签: c# generics keyvaluepair


【解决方案1】:

你不能完全那样做,这是行不通的。

想象你可以写出以下内容:

public class KeyValuePairs
{
    public string Key { get; set; }
    public T Value<T> { get; set; }
}

以下代码中foo 变量的类型是什么?

var pair = new KeyValuePairs();
var foo = pair.Value;

好的,现在让我们假设语言允许你这样做:

var pair = new KeyValuePairs();
var foo = pair.Value<int>;

嗯……下面的代码会如何表现?

var pair = new KeyValuePairs();
pair.Value = new Thread();
var foo = pair.Value<int>;

如您所见,语言不允许这样做是有充分理由的。


当然,您可以通过以下方式进行:

public class KeyValuePairs<TValue>
{
    public string Key { get; set; }
    public TValue Value { get; set; }
}

(或只使用System.Collections.Generic.KeyValuePair&lt;string, TValue&gt;

或者您可以将属性替换为方法对:

// Warning: bad code!
public class KeyValuePairs<TValue>
{
    private object _value;

    public string Key { get; set; }

    public TValue GetValue<TValue>()
    {
        return _value;
    }

    public void SetValue<TValue>(TValue value)
    {
        _value = value;
    }
}

但如果您考虑这样做,显然会遇到设计问题,因为与object-typed 属性相比,这没有任何优势。 p>


这是使用KeyValuePair&lt;string, object&gt;的解决方案:

var list = new List<KeyValuePair<string, object>>();
list.Add(new KeyValuePair<string, object>("string", "Hello, World!"));
list.Add(new KeyValuePair<string, object>("int", 42));
list.Add(new KeyValuePair<string, object>("bool", true));

foreach (var item in list)
    Console.WriteLine("[{0}] = {1}", item.Key, item.Value);

这是demo

【讨论】:

  • 使类通用的问题是我将类用作列表,如 List objList = new List();这只是意味着所有的键和值都是int,或者你在初始化时提供的任何东西,但在我的例子中,值的值可以是任何类型,我也不能让它成为对象类型,因为我无法获得属性被分配到的实际类型。
  • 那你可以直接使用KeyValuePair&lt;string, object&gt;...这种方式有什么问题?
  • 假设我在 KeyValuePair 中有 2 项 1. 字符串,整数,例如:“abbas”,123 2. 字符串,布尔值,例如:“abbas”,以上初始化为真将始终将 value 参数的类型作为对象而不是 int 和 boolean,这是实际的问题,希望我现在清楚,符合我的要求
  • 这仍然可以工作,因为值类型会被装箱。然后,您可以将值转换回您想要的类型(或使用 is/as 测试给定类型,或使用 Value.GetType() 获取运行时类型)。
  • 如果你不介意,你能给我举个例子,其中 KeyValuePairs 中有 2 个项目,其中一个应该是 string,int,另一个应该是 string,boolean,下面我试过了,但没有奏效: List> inserts = new List>(); inserts.Add(new KeyValuePairs("abbas", "123"));它期望一旦为 KeyValuePairs 定义的 Generic 类型应该用于列表中的所有项目。
【解决方案2】:

简短的回答是:

public class KeyValuePairs<TValue>
{
    public string Key { get; set; }
    public TValue Value { get; set; }
}

长篇大论是:为什么不将System.Collections.Generic.KeyValuePair&lt;TKey,TValue&gt; 结构与string 一起用于TKey 以及对TValue 有用的任何东西?

泛型类示例:

var key = new KeyValuePairs<int>{ Key = "abc", Value = 123 };

我会让键不可变,因为一旦对象被添加到依赖于键的集合中,更改它不是一个好主意:

public class KeyValuePairs<TValue>
{
    public KeyValuePairs(string key, TValue value)
    {
        _key = key;
        Value = value;
    }

    private readonly string _key;
    public string Key { get { return _key; } }

    public TValue Value { get; set; }
}

例子:

var key = new KeyValuePairs<int>("abc", 123);

【讨论】:

    【解决方案3】:

    如果您不知道如何执行此操作,我建议您在继续之前进一步阅读泛型(开始here)。为了启发您,可以通过以下代码来实现。

    public class KeyValuePairs<T>
    {
        public string Key { get; set; }
        public T Value { get; set; }
    }
    

    但是,像这样的类已经存在于System.Collections.Generic 命名空间中。 KeyValuePair.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      相关资源
      最近更新 更多