c# - 如何在 C# 中对模板使用 new 运算符

标签 c# .net list templates

我正在尝试了解如何在 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/

相关文章:

c# - .NET 框架库是否被视为用户定义的?

sql - 连接 R 列表中的键值对

java - 如何对列表中两个不同类的字段进行排序?

c# - 面经应用

c# - 在没有线程锁定的情况下通过同步 c# 调用异步

c# - 根据组数对列表进行排序

c# - 处理导致空序列等的 LINQ 语句的最佳实践?

.net - .NET 世界中的 ORM 和 SOA

.net - 图像 UriSource 和数据绑定(bind)

list - 方案:这两个列表是否具有相同的内存表示?