【问题标题】:Test if generic type supports ICloneable测试泛型是否支持 ICloneable
【发布时间】:2016-06-07 20:35:34
【问题描述】:

我有一个名为 ValueFrequency 的结构体,它作为一个结构体开始它的生命,您(出于统计原因)可以在其中存储一个(双精度)值和一个(整数)频率(说明该值在一组数据中出现的次数. 例如,如果你有一个列表/数组的值:1,1,1,2,2,3,4,4,4,4,4 它可以存储为 ValueFrequency 的列表/数组,而不是:(1 ,3),(2,2),(3,1),(4,5)。

无论如何,我发现我可以使用泛型而不是硬编码我的 scruct 以使用 double,这样我就可以将它与外部数据类型一起使用(例如,当使用它来存储来自二维数据集的数据时,Point )。

结构的简化版:

public struct ValueFrequency<T> : IComparable, ICloneable where T : IComparable
{
  public T value;
  public int Frequency;
}

我的问题是我想将此结构与支持 ICloneable 和 ValueTypes(如 double)的结构/类一起使用。我将如何编写一个复制构造函数(从另一个 ValueFrequncy 复制其字段),如果结构/类支持 IClonable,它将简单地分配相同的值(如果类型是 ValueType)或克隆:

public ValueFrequency(ValueFrequency<T> valueFrequency)
{
  if (typeof(T).IsValueType)
    this.Value = valueFrequency.Value;
  else if (T is supporting IClonable)  // pseudo-code ???
    this.Value = (T)valueFrequency.Value.Clone();
  else
    throw new Exception("T must be ValueType or IClonable") ;
  this.Frequency = valueFrequency.Frequency;
}

如您所见,我的问题是测试 T 是否为 IClonable,以及实际的克隆(将 T 类型转换为 IClonable 以执行克隆)。

【问题讨论】:

    标签: c# generics value-type icloneable


    【解决方案1】:

    您是否关心 type 实现 ICloneable 还是只是底层 objectICloneable

    else if (valueFrequency.Value is ICloneable) 
        this.Value = (T)((ICloneable)valueFrequency.Value).Clone();
    

    【讨论】:

      【解决方案2】:

      您可以像这样使用IsAssignableFrom 方法:

       bool is_cloneable = typeof(ICloneable).IsAssignableFrom(typeof(T));
      

      或者您可以将valueFrequency.Value 转换为ICloneable 并测试它是否不是null,如下所示:

      ICloneable value_as_cloneable = valueFrequency.Value as ICloneable;
      
      if(value_as_cloneable != null)
          this.Value = (T)value_as_cloneable.Clone();
      

      【讨论】:

        【解决方案3】:

        感谢你们(Yacoub Massad 和 D Stanley),我最终实现了你们的两个解决方案。我决定以下 我的(副本)构造函数的实现(实现了 D Stanley 的建议):

        public ValueFrequency(ValueFrequency<T> valueFrequency)
        {
            if (valueFrequency.Value is ICloneable)
                Value = (T)((ICloneable)valueFrequency.Value).Clone();
            else
                Value = valueFrequency.Value;
            _frequency = valueFrequency.Frequency;
        }
        

        此结构的另一种方法可以采用 ValueFrequency 的 IEnumerable(它保存一个值 (T) 和一个频率 (int))并将其“解包”到一个值列表 (T) 中,其中每个值重复多次次数为频率(此方法实现了 Yacoub Massad 的建议):

        public static List<T> ListOfValueFrequencyToList(IEnumerable<ValueFrequency<T>> valueFrequencyList)
        {
            bool isCloneable = typeof(ICloneable).IsAssignableFrom(typeof(T));
            List<T> result = new List<T>();
            foreach (ValueFrequency<T> vf in valueFrequencyList)
            {
                for (int i = 0; i < vf.Frequency; i++)
                {
                    if (isCloneable)
                        result.Add((T)((ICloneable)vf.Value).Clone());
                    else
                        result.Add(vf.Value);
                }
            }
            return result;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-11
          • 2014-03-21
          • 1970-01-01
          • 2016-09-18
          相关资源
          最近更新 更多