Không có nghĩa là gì trong đó T: class, new () có nghĩa là gì?


Câu trả lời:


329

Đó 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 Tkhông thể là một int, float, double, DateTimehoặc bất kỳ khác struct(kiểu giá trị).

Nó có thể là một stringhoặ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ố.


5
Chỉ cần làm rõ, nếu bạn không có mệnh đề lớp như một phần của T ..., thì có thể sử dụng int, float, double, v.v.
AboutDev

1
@ AboutDev đúng, bạn không phải đặt các ràng buộc cho tham số loại chung của mình. Nhưng nếu bạn đang tạo một cái chung dự kiến ​​chỉ hoạt động trên các loại tham chiếu hoặc giá trị, thì bạn nên chỉ định. Không có ràng buộc, bạn có thể mong đợi các loại tham chiếu (lớp) hoặc loại giá trị (structs (int, float, double ...)).
NerdFury

1
Điều gì về nơi T: [tên giao diện], new ()? Bạn vẫn cần phải có một hàm tạo không tham số?
Vince Tino

3
Để làm rõ nhận xét của Justin, một hàm tạo trống không có câu lệnh nào (như hàm tạo mặc định) trong khi hàm tạo không tham số có thể chứa các câu lệnh (như khởi tạo danh sách).
DharmaTurtle

@VinceTino: new()chỉ định chính xác "phải có một hàm tạo không tham số công khai"
Flater

162

Đó 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 Tphải là loại tham chiếu (không phải loại giá trị).

where T : new()

Có nghĩa là loại Tphả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()

Điểm tốt cho thứ hai và thứ ba, chỉ để thêm thông tin, tôi nghĩ rằng điểm thứ hai là hữu ích khi thực hiện phản xạ trong loại chung. ví dụ. T t = mới T (); t.GetType (). GetProperty ("ID"). SetValue (t, uniqueId, null);
Jerry Liang

1
Tôi tin rằng không cần thiết phải nói nơi T: class, new (), vì new () đã ngụ ý lớp vì các cấu trúc không thể có các hàm tạo mặc định.
DharmaTurtle

@DharmaTurtle, "structs không thể chứa các hàm tạo không tham số rõ ràng", không có nghĩa là chúng không có, nó nói rằng bạn không thể định nghĩa một. nguồn: msdn.microsoft.com/tr-tr/l
Library / aa288208 (v = vs.71) .aspx

121

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.


23
Điều này rất hữu ích, nhưng liên kết đến nguồn .
Skean

26

class& newlà 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 Tphả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
}

1
Thuyết minh tốt. Cảm ơn.
Subhan Ali

15

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();
    }
}

6

Điều đó có nghĩa là kiểu Tđó phải là một lớp 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();

1
không chỉ là một constructor, mà là một constructor không có đối số.
NerdFury

@NerdFury: Cảm ơn. Đó là một chút quan trọng. Đã sửa.
Evan Mulawski

5

trong đó (Tham khảo C #)

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ó Tphả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.


4

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.


1

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.


1

Đâ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.


0

Khi sử dụng lớp trong các ràng buộc, điều đó có nghĩa là bạn chỉ có thể sử dụng Kiểu tham chiếu, một điều cần thêm là khi sử dụng ràng buộc mới () , đó phải là điều cuối cùng bạn viết trong các điều khoản ràng buộc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.