Apa arti "di mana T: kelas, baru ()"?


Jawaban:


329

Itu adalah kendala pada parameter generik T. Itu harus berupa class(tipe referensi) dan harus memiliki konstruktor default parameter-kurang publik.

Itu berarti Ttidak bisa menjadi int, float, double, DateTimeatau lainnya struct(value type).

Itu bisa berupa string, atau jenis referensi khusus lainnya, asalkan memiliki konstruktor default atau kurang parameter.


5
Hanya untuk memperjelas, jika Anda tidak memiliki klausa kelas sebagai bagian dari tempat T ..., maka aman untuk menggunakan int, float, dobel dll.
AboutDev

1
@ AgoutDev benar, Anda tidak perlu membatasi parameter tipe generik Anda. Tetapi jika Anda membuat generik yang mengharapkan hanya bekerja pada tipe referensi atau nilai, maka Anda harus menentukan. Tanpa kendala, Anda dapat mengharapkan tipe referensi (kelas) atau tipe nilai (struct (int, float, double ...)).
NerdFury

1
Bagaimana dengan di mana T: [nama antarmuka], baru ()? Apakah Anda masih perlu memiliki konstruktor tanpa parameter?
Vince Tino

3
Untuk mengklarifikasi komentar Justin, konstruktor kosong tidak memiliki pernyataan (seperti konstruktor default) sementara konstruktor tanpa parameter dapat berisi pernyataan (seperti menginisialisasi daftar).
DharmaTurtle

@VinceTino: new()secara spesifik menentukan "harus memiliki konstruktor tanpa parameter publik"
Flater

162

Itu adalah batasan tipe generik. Dalam kasus Anda ada dua:

where T : class

Berarti tipe tersebut Tharus tipe referensi (bukan tipe nilai).

where T : new()

Berarti tipe tersebut Tharus memiliki konstruktor tanpa parameter. Memiliki batasan ini akan memungkinkan Anda untuk melakukan sesuatu seperti T field = new T();dalam kode Anda yang tidak dapat Anda lakukan sebaliknya.

Anda kemudian menggabungkan keduanya menggunakan koma untuk mendapatkan:

where T : class, new()

Poin bagus untuk kedua dan ketiga, hanya untuk menambah informasi, saya pikir poin kedua berguna ketika melakukan refleksi dalam tipe generik. misalnya. T t = T baru (); t.GetType (). GetProperty ("ID"). SetValue (t, uniqueId, null);
Jerry Liang

1
Saya percaya itu berlebihan untuk mengatakan di mana T: class, new (), karena new () sudah menyiratkan kelas karena struct tidak dapat memiliki konstruktor default.
DharmaTurtle

@ DharmaTurtle, "struct tidak dapat mengandung konstruktor tanpa parameter eksplisit", tidak berarti mereka tidak memilikinya, ia mengatakan bahwa Anda tidak dapat mendefinisikan satu. sumber: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
rustem

121

di mana T: struct

Argumen tipe harus tipe nilai. Jenis nilai apa pun kecuali Nullable dapat ditentukan. Lihat Menggunakan Jenis Nullable (Panduan Pemrograman C #) untuk informasi lebih lanjut.

dimana T: kelas

Argumen tipe haruslah tipe referensi, termasuk kelas, antarmuka, delegasi, atau tipe array apa pun. (Lihat catatan di bawah.)

di mana T: new () Argumen tipe harus memiliki konstruktor tanpa parameter publik. Ketika digunakan bersama dengan batasan lain, batasan baru () harus ditentukan terakhir.

di mana T: [nama kelas dasar]

Argumen tipe harus atau berasal dari kelas dasar yang ditentukan.

di mana T: [nama antarmuka]

Argumen tipe harus atau mengimplementasikan antarmuka yang ditentukan. Beberapa batasan antarmuka dapat ditentukan. Antarmuka pembatas juga bisa bersifat generik.

dimana T: U

Argumen tipe yang disediakan untuk T harus atau berasal dari argumen yang disediakan untuk U. Ini disebut batasan tipe polos.


23
Ini berguna, tetapi tautan ke sumber .
Skean

26

class& new2 kendala pada parameter tipe generikT .
Masing-masing memastikan:

class

Argumen tipe harus merupakan tipe referensi; ini berlaku juga untuk semua kelas, antarmuka, delegasi, atau tipe array.

new

Argumen tipe harus memiliki konstruktor tanpa parameter publik. Ketika digunakan bersama dengan batasan lain, batasan baru () harus ditentukan terakhir.

Kombinasi mereka berarti bahwa tipe tersebut Tharuslah Tipe Referensi (tidak boleh menjadi Tipe Nilai ), dan harus memiliki konstruktor tanpa parameter.

Contoh:

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
Demonstrasi yang bagus. Terima kasih.
Subhan Ali

15

new (): Menentukan batasan new () berarti tipe T harus menggunakan konstruktor tanpa parameter, sehingga objek dapat dipakai dari situ - lihat Konstruktor default .

class: Berarti T harus menjadi tipe referensi sehingga tidak bisa berupa int, float, double, DateTime atau struct lainnya (tipe nilai).

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

Itu berarti tipe itu Tharus kelas dan memiliki konstruktor yang tidak mengambil argumen apa pun.

Misalnya, Anda harus dapat melakukan ini:

T t = new T();

1
bukan hanya konstruktor, tetapi juga konstruktor yang tidak menggunakan argumen.
NerdFury

@ NerdFury: Terima kasih. Itu sedikit penting. Dikoreksi.
Evan Mulawski

5

dimana (C # Referensi)

Kendala baru () membuat kompiler tahu bahwa argumen tipe apa pun yang diberikan harus memiliki konstruktor tanpa parameter - atau default--

Jadi seharusnya, Tharus berupa kelas, dan memiliki parameterless yang dapat diakses - atau konstruktor default.


4

Apa yang muncul setelah "Di mana" adalah kendala pada tipe T generik yang Anda nyatakan, jadi:

  • kelas berarti bahwa T harus kelas dan bukan tipe nilai atau struct.

  • baru () menunjukkan bahwa kelas T harus memiliki konstruktor default bebas parameter publik yang telah ditentukan.


1

Ini disebut 'kendala' pada parameter generik T. Ini berarti bahwa T harus menjadi tipe referensi (kelas) dan harus memiliki konstruktor default publik.


1

Ini adalah bagian dari mekanisme Generics, di mana kata kunci menambahkan batasan pada tipe apa yang harus diterapkan agar dapat digunakan sebagai parameter tipe.


0

ketika menggunakan kelas dalam batasan itu berarti Anda hanya bisa menggunakan tipe Referensi, hal lain yang harus ditambahkan adalah kapan harus menggunakan kendala baru () , itu harus menjadi hal terakhir yang Anda tulis dalam istilah Kendala.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.