测试泛型类型是否支持ICloneable

时间:2016-06-07 20:35:35

标签: c# generics value-type icloneable

我有一个名为ValueFrequency的结构,它以结构开始,你可以存储一个(双重)值和一个(int)频率(告诉你在一组数据中出现这个值的次数)。例如,如果你有一个列表/数组的值为1,1,1,2,2,3,4,4,4,4,4它可以存储为ValueFrequency的列表/数组:(1 ,3),(2,2),(3,1),(4,5)。

无论如何,我发现用硬编码我的scruct来使用double我可以使用泛型,所以我可以将它用于其他数据类型(例如Point,当使用它来存储来自2维数据集的数据时)。

结构的简化版本:

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

我的问题是我想将这个结构用于支持ICloneable和ValueTypes的结构/类,例如double。我如何编写一个拷贝构造函数(从另一个ValueFrequncy复制它的字段),它将简单地分配相同的值(如果type为ValueType)或者如果struct / class支持IClonable则克隆:

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来执行克隆)。

3 个答案:

答案 0 :(得分:3)

您是否关心类型实现ICloneable或只是基础对象ICloneable

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

答案 1 :(得分: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();

答案 2 :(得分:0)

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

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;
}

这个结构的另一种方法可以采用IEnumerable的ValueFrequency(它包含一个值(T)和一个Frequency(int))和&#34; unpack&#34;它进入一个值列表(T),其中每个值重复频率的次数(此方法实现了Yacoub Massad的建议):

@Service
class StartService{
   private boolean active;
   public void setActive(boolean active){this.active=active;}


   @Scheduled(fixedRate=5000)
   public void doStuff(){
      if(!active)return;
      // do actual stuff here
   }

}