#1:带有接口的新约束
添加一个约束来TValue
告诉编译器它有一个无参数的构造函数。您可以通过将关键字添加new
到TValue
. 这样你至少可以构建一个项目。
您不能使用泛型参数类型的参数。但是您可以使用另一个约束来定义一些属性:
public interface IMyValue<TValue>
{
void CopyFrom(TValue original);
}
public static List<TValue> deepCopyList<TValue>(List<TValue> src)
where TValue: IMyValue<TValue>, new() // <== Setting the constraints of TValue.
{
List<TValue> arr = new List<TValue>();
for (int i = 0; i < src.Count; i++)
{
TValue value = new TValue();
value.CopyFrom(src[i]);
arr.Add(value); // No error.
}
return arr;
}
#2:使用 ICloneable
还有第二种解决方案,它有点相同。使值负责关闭它自己,使用ICloneable
:
public static List<TValue> deepCopyList<TValue>(List<TValue> src)
where TValue: ICloneable // <== Setting the constraints of TValue.
{
List<TValue> arr = new List<TValue>();
for (int i = 0; i < src.Count; i++)
{
TValue value = (TValue)src[i].Clone();
arr.Add(value); // No error.
}
return arr;
}
#3:使用激活器
但既然你想创建一个深度克隆,还有另一种方法,使用Activator
. 此方法不是类型安全的,并且当类型不支持该构造函数调用时会产生运行时异常:
public static List<TValue> deepCopyList<TValue>(List<TValue> src)
{
List<TValue> arr = new List<TValue>();
for (int i = 0; i < src.Count; i++)
{
TValue value = (TValue)Activator.CreateInstance(typeof(TValue), src[i]);
arr.Add(value); // Possible runtime rror.
}
return arr;
}
上述方法也可以通过使用反射替换并获得正确ConstructorInfo
并使用它来创建新项目。做同样的事情Activator
并具有同样的风险。
顺便说一句:在 C# 中,它被称为“通用”,而不是 C++ 中的“模板”。