根据MSDN,new()
约束用于确保类型参数必须具有公共无参数构造函数。但是,请考虑下面给出的示例(取自同一页(。
public class Employee
{
public Employee(string name, int id)
{
Name = name;
ID = id;
}
public string Name { get; set; }
public int ID { get; set; }
}
class EmployeeList<T> where T : Employee, new()
{
}
这里,Employee
类型没有无参数/默认构造函数,但此代码编译成功。有人能详细说明一下这个约束的用法以及为什么它有效吗?
编译代码是因为完全可以使用无参数构造函数从Employee
派生类型,而约束就是这么说的。约束是而不是试图说Employee
本身有一个无参数构造函数,事实上,由于不满足约束,使用EmployeeList<Employee>
的尝试将失败。
作为有效的示例:
public class GeneratedEmployee : Employee
{
public GeneratedEmployee() : base(GenerateName(), GenerateId())
{
}
private static string GenerateName()
{
// Implementation here
}
private static int GenerateId()
{
// Implementation here
}
}
此时,可以创建一个EmployeeList<GeneratedEmployee>
,并且假设EmployeeList<>
类在实现中的某个地方使用new()
,它将调用GeneratedEmployee
的无参数构造函数。
也就是说,这是一个非常奇怪的约束,因为我不希望你真的想在不指定姓名和ID的情况下创建一名员工。
这里,Employee类型没有无参数/默认构造函数,但此代码成功编译
这是正确的,但是您没有尝试实际使用该类。没有编译的实际上是试图调用EmployeeList<Employee>
:
CS0310 'Employee' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'EmployeeList<T>'
正如您正确引用的,Employee
与约束T : Employee, new()
不匹配。给它提供与之匹配的东西的唯一方法是从Employee
派生一个实现默认构造函数的类,并提供它。
您的列表指出该类必须是Employee,或者派生自Employees。Employee本身没有无参数构造函数,因此它将作为类型参数失败:
//fails to compile
var xx = new EmployeeList<Employee>()
但是,如果您定义了一个从Employee继承的类:
public class EmployeeDerived : Employee
{
public EmployeeDerived() : base("test", 123)
{
}
}
这个类确实有一个无参数构造函数(尽管它非常无用(。因此编译器可以将其用作EmployeeList 的T
即使Employee
没有无参数构造函数,Employee
的子类也可以!
public class Manager: Employee {
// these parameters don't make sense - just an example
public EmployeeSubclass(): base("foo", 1) {
}
}
然后我可以使用Manager
作为EmployeeList
-EmployeeList<Manager>
的类型参数。它同时满足两个约束!
class EmployeeList<T> where T : Employee, new()
{
}
T
必须是具有无参数构造函数的Employee
的Employee
子代,但Employee
没有构造函数并不意味着它的子代不能有。
即new()
约束将阻止new EmployeeList<Employee>();
编译,但您可以执行:
class EmployeeChild : Employee
{
public EmployeeChild() : base("", 1)
{
}
}
这将满足所有约束,并且new EmployeeList<EmployeeChild>();
将编译得很好。