Câu trả lời:
Đó là một ràng buộc về tham số chung T
. Nó phải là class
(kiểu tham chiếu) và phải có hàm tạo mặc định không tham số công khai.
Điều đó có nghĩa T
không thể là một int
, float
, double
, DateTime
hoặc bất kỳ khác struct
(kiểu giá trị).
Nó có thể là một string
hoặc bất kỳ loại tham chiếu tùy chỉnh nào khác, miễn là nó có một hàm tạo mặc định hoặc không có tham số.
new()
chỉ định chính xác "phải có một hàm tạo không tham số công khai"
Đó là những hạn chế loại chung. Trong trường hợp của bạn có hai trong số họ:
where T : class
Có nghĩa là loại T
phải là loại tham chiếu (không phải loại giá trị).
where T : new()
Có nghĩa là loại T
phải có một hàm tạo không tham số. Có ràng buộc này sẽ cho phép bạn làm một cái gì đó giống như T field = new T();
trong mã của bạn mà bạn không thể làm khác được.
Sau đó, bạn kết hợp cả hai bằng dấu phẩy để có được:
where T : class, new()
trong đó T: struct
Đối số loại phải là một loại giá trị. Bất kỳ loại giá trị nào ngoại trừ Nullable đều có thể được chỉ định. Xem Sử dụng các loại không thể (Hướng dẫn lập trình C #) để biết thêm thông tin.
trong đó T: lớp
Đối số kiểu phải là kiểu tham chiếu, bao gồm mọi lớp, giao diện, ủy nhiệm hoặc kiểu mảng. (Xem ghi chú bên dưới.)
Trong đó T: new () Đối số kiểu phải có hàm tạo không tham số công khai. Khi được sử dụng cùng với các ràng buộc khác, ràng buộc () mới phải được chỉ định sau cùng.
Trong đó T: [tên lớp cơ sở]
Đối số kiểu phải hoặc xuất phát từ lớp cơ sở đã chỉ định.
Trong đó T: [tên giao diện]
Đối số kiểu phải hoặc thực hiện giao diện đã chỉ định. Nhiều ràng buộc giao diện có thể được chỉ định. Giao diện ràng buộc cũng có thể là chung chung.
trong đó T: U
Đối số loại được cung cấp cho T phải hoặc xuất phát từ đối số được cung cấp cho U. Đây được gọi là ràng buộc kiểu trần.
class
& new
là 2 ràng buộc trên tham số loại chungT
.
Họ tôn trọng:
class
Đối số kiểu phải là kiểu tham chiếu; điều này cũng áp dụng cho bất kỳ lớp, giao diện, đại biểu hoặc loại mảng.
new
Đối số kiểu phải có hàm tạo tham số công khai. Khi được sử dụng cùng với các ràng buộc khác, ràng buộc () mới phải được chỉ định sau cùng.
Sự kết hợp của chúng có nghĩa là loại T
phải là Loại tham chiếu (không thể là Loại giá trị ) và phải có hàm tạo không tham số.
Thí dụ:
struct MyStruct { } // structs are value types
class MyClass1 { } // no constructors defined, so the class implicitly has a parameterless one
class MyClass2 // parameterless constructor explicitly defined
{
public MyClass2() { }
}
class MyClass3 // only non-parameterless constructor defined
{
public MyClass3(object parameter) { }
}
class MyClass4 // both parameterless & non-parameterless constructors defined
{
public MyClass4() { }
public MyClass4(object parameter) { }
}
interface INewable<T>
where T : new()
{
}
interface INewableReference<T>
where T : class, new()
{
}
class Checks
{
INewable<int> cn1; // ALLOWED: has parameterless ctor
INewable<string> n2; // NOT ALLOWED: no parameterless ctor
INewable<MyStruct> n3; // ALLOWED: has parameterless ctor
INewable<MyClass1> n4; // ALLOWED: has parameterless ctor
INewable<MyClass2> n5; // ALLOWED: has parameterless ctor
INewable<MyClass3> n6; // NOT ALLOWED: no parameterless ctor
INewable<MyClass4> n7; // ALLOWED: has parameterless ctor
INewableReference<int> nr1; // NOT ALLOWED: not a reference type
INewableReference<string> nr2; // NOT ALLOWED: no parameterless ctor
INewableReference<MyStruct> nr3; // NOT ALLOWED: not a reference type
INewableReference<MyClass1> nr4; // ALLOWED: has parameterless ctor
INewableReference<MyClass2> nr5; // ALLOWED: has parameterless ctor
INewableReference<MyClass3> nr6; // NOT ALLOWED: no parameterless ctor
INewableReference<MyClass4> nr7; // ALLOWED: has parameterless ctor
}
new (): Chỉ định ràng buộc new () có nghĩa là loại T phải sử dụng hàm tạo không tham số, do đó, một đối tượng có thể được khởi tạo từ nó - xem Các hàm tạo mặc định .
class: Có nghĩa là T phải là một kiểu tham chiếu để nó không thể là int, float, double, DateTime hoặc struct khác (kiểu giá trị).
public void MakeCars()
{
//This won't compile as researchEngine doesn't have a public constructor and so can't be instantiated.
CarFactory<ResearchEngine> researchLine = new CarFactory<ResearchEngine>();
var researchEngine = researchLine.MakeEngine();
//Can instantiate new object of class with default public constructor
CarFactory<ProductionEngine> productionLine = new CarFactory<ProductionEngine>();
var productionEngine = productionLine.MakeEngine();
}
public class ProductionEngine { }
public class ResearchEngine
{
private ResearchEngine() { }
}
public class CarFactory<TEngine> where TEngine : class, new()
{
public TEngine MakeEngine()
{
return new TEngine();
}
}
Điều đó có nghĩa là kiểu T
đó phải là một lớp và có một hàm tạo không có bất kỳ đối số nào.
Ví dụ: bạn phải có khả năng làm điều này:
T t = new T();
Ràng buộc mới () cho phép trình biên dịch biết rằng bất kỳ đối số kiểu nào được cung cấp phải có một tham số có thể truy cập - hoặc mặc định--
Vì vậy, nó T
phải là một lớp và có một tham số mặc định có thể truy cập - hoặc hàm tạo mặc định.
Cái gì xuất hiện sau "Where" là một ràng buộc đối với loại T chung mà bạn đã khai báo, vì vậy:
lớp có nghĩa là T phải là một lớp và không phải là một loại giá trị hoặc một cấu trúc.
new () chỉ ra rằng lớp T nên có một hàm tạo mặc định không có tham số công khai được xác định.
Nó được gọi là 'ràng buộc' trên tham số chung T. Điều đó có nghĩa là T phải là loại tham chiếu (một lớp) và nó phải có một hàm tạo mặc định công khai.
Đây là một phần của cơ chế Generics, trong đó từ khóa thêm các ràng buộc vào loại nào phải triển khai để được sử dụng làm tham số loại.