简体   繁体   English

类型参数的约束 - new()

[英]Constraints on type parameters - new()

As per MSDN , the new() constraint is used to ensure that the type argument must have a public parameterless constructor .根据MSDNnew()约束用于确保类型参数必须具有公共无参数构造函数 However, consider the example given below (taken from the same page).但是,请考虑下面给出的示例(取自同一页面)。

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()
{

}

Here, the Employee type does not have a parameterless/default constructor, yet this code compiles successfully.在这里, Employee类型没有无参数/默认构造函数,但此代码编译成功。 Can someone please elaborate on the usage of this constraint and why this works?有人可以详细说明这个约束的用法以及为什么会这样吗?

The code compiles because it's entirely possible to have a type derived from Employee with a parameterless constructor - and that's what the constraint says.代码可以编译,因为完全有可能使用无参数构造函数从Employee派生类型 - 这就是约束所说的。 The constraint is not trying to say that Employee itself has a parameterless constructor, and indeed an attempt to use EmployeeList<Employee> would fail as the constraint isn't satisfied.约束并不是Employee本身有一个无参数的构造函数,实际上使用EmployeeList<Employee>的尝试会因为约束不满足而失败。

As example of what would be valid:作为有效示例:

public class GeneratedEmployee : Employee
{
    public GeneratedEmployee() : base(GenerateName(), GenerateId())
    {
    }

    private static string GenerateName()
    {
        // Implementation here
    }

    private static int GenerateId()
    {
        // Implementation here
    }
}

At that point, it's fine to create an EmployeeList<GeneratedEmployee> , and assuming the EmployeeList<> class uses new() somewhere in the implementation, it would call the parameterless constructor of GeneratedEmployee .此时,可以创建一个EmployeeList<GeneratedEmployee> ,并假设EmployeeList<> class 在实现中的某处使用new() ,它将调用GeneratedEmployee的无参数构造函数。

That said, it's a pretty odd constraint, as I wouldn't expect you to really want to create an employee without specifying the name and ID.也就是说,这是一个非常奇怪的约束,因为我不希望您真的想在不指定名称和 ID 的情况下创建员工。

class EmployeeList<T> where T : Employee, new()
{

}

T must be Employee descendant of Employee with parameterless constructor but the fact that Employee does not have one does not mean that it's descendants can't have it. T必须是具有无参数构造函数的EmployeeEmployee后代,但Employee没有这一事实并不意味着它的后代不能拥有它。

ie new() constraint will prevent new EmployeeList<Employee>();new()约束将阻止new EmployeeList<Employee>(); from compiling, but you can do:从编译,但你可以这样做:

class EmployeeChild : Employee
{
    public EmployeeChild() : base("", 1)
    {
    }
}

Which will satisfy all constraints and new EmployeeList<EmployeeChild>();这将满足所有约束和new EmployeeList<EmployeeChild>(); will compile just fine.会编译得很好。

Your list says that the class must be an Employee, or derived from Employee.您的列表显示 class 必须是 Employee 或派生自 Employee。 Employee itself does not have a parameterless constructor, so it would fail as the type argument: Employee 本身没有无参数构造函数,因此它会作为类型参数失败:

//fails to compile
var xx = new EmployeeList<Employee>()

But, if you defined a class that inherited from Employee:但是,如果您定义了一个继承自 Employee 的 class:

public class EmployeeDerived : Employee
{
    public EmployeeDerived() : base("test", 123)
    {

    }
}

This class does have a parameterless constructor (though it's pretty useless).这个 class 确实有一个无参数的构造函数(尽管它非常没用)。 So the compiler can use it as the T to EmployeeList因此编译器可以将其用作 EmployeeList 的T

Even though Employee doesn't have a parameterless constructor, a subclass of Employee can !即使Employee没有无参数构造函数, Employee的子类也可以

public class Manager: Employee {
    // these parameters don't make sense - just an example
    public EmployeeSubclass(): base("foo", 1) {
        
    }
}

Then I can use Manager as the type argument for EmployeeList - EmployeeList<Manager> .然后我可以使用Manager作为EmployeeList - EmployeeList<Manager>的类型参数。 It satisfies both constraints!它满足两个约束!

Here, the Employee type does not have a parameterless/default constructor, yet this code compiles successfully在这里,Employee 类型没有无参数/默认构造函数,但此代码编译成功

That's correct, however what you haven't tried is to actually use the class.没错,但是您没有尝试过的是实际使用 class。 What doesn't compile is actually trying to call EmployeeList<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>'

As you correctly quote, Employee doesn't match the constraint T: Employee, new() .正如您正确引用的那样, Employee与约束T: Employee, new()不匹配。 The only way to give it something that will match it is to derive a class from Employee that does implement a default constructor, and provide that.给它匹配的东西的唯一方法是从Employee派生一个 class ,它确实实现了默认构造函数,并提供它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM