测试泛型类型是否支持ICloneable



我有一个名为ValueFrequency的结构,它的生命开始时是一个结构,你(出于统计原因)可以在其中存储一个(double)值和一个(int)频率(告诉这个值在一组数据中发生了多少次。例如,如果你有一个值为:1,1,1,2,2,3,4,4,4,4的列表/数组,它可以存储为ValueFrench的列表/阵列,而不是:(1,3),(2,2),(3,1),(4,5)。

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

结构的简化版本:

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

我的问题是,我想将这个结构与支持ICloneable和类似double的ValueTypes的结构/类一起使用。我该如何编写复制构造函数(从另一个ValueFrequency复制其字段),其中它将简单地分配相同的值(如果类型为ValueType)或克隆(如果结构/类支持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以执行克隆)。

您关心类型实现ICloneable还是只关心底层对象ICloneable

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

您可以像这样使用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();

感谢你们(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)和一个Frequency(int)),并将其"解压"为一个值列表(T),其中每个值的重复次数与Frequency相同(该方法实现了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;
}

相关内容

  • 没有找到相关文章

最新更新