我正在尝试了解如何在 C# 中使用模板。我写了这个:
public static List<TValue> deepCopyList<TValue>(List<TValue> src)
{
List<TValue> arr = new List<TValue>();
for (int i = 0; i < src.Count; i++)
{
arr.Add(new TValue(src[i])); //Error on this line
}
return arr;
}
但是我得到一个错误:
error CS0304: Cannot create an instance of the variable type 'TValue' because it does not have the new() constraint
最佳答案
#1: 接口(interface)的新约束
向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
使值负责 self 克隆:
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++ 中的"template"。
关于c# - 如何在 C# 中对模板使用 new 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16730917/