Jawaban:
Itu adalah kendala pada parameter generik T
. Itu harus berupa class
(tipe referensi) dan harus memiliki konstruktor default parameter-kurang publik.
Itu berarti T
tidak bisa menjadi int
, float
, double
, DateTime
atau lainnya struct
(value type).
Itu bisa berupa string
, atau jenis referensi khusus lainnya, asalkan memiliki konstruktor default atau kurang parameter.
new()
secara spesifik menentukan "harus memiliki konstruktor tanpa parameter publik"
Itu adalah batasan tipe generik. Dalam kasus Anda ada dua:
where T : class
Berarti tipe tersebut T
harus tipe referensi (bukan tipe nilai).
where T : new()
Berarti tipe tersebut T
harus 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()
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.
class
& new
2 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 T
haruslah 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
}
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();
}
}
Itu berarti tipe itu T
harus kelas dan memiliki konstruktor yang tidak mengambil argumen apa pun.
Misalnya, Anda harus dapat melakukan ini:
T t = new T();
Kendala baru () membuat kompiler tahu bahwa argumen tipe apa pun yang diberikan harus memiliki konstruktor tanpa parameter - atau default--
Jadi seharusnya, T
harus berupa kelas, dan memiliki parameterless yang dapat diakses - atau konstruktor default.
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.
Ini disebut 'kendala' pada parameter generik T. Ini berarti bahwa T harus menjadi tipe referensi (kelas) dan harus memiliki konstruktor default publik.
Ini adalah bagian dari mekanisme Generics, di mana kata kunci menambahkan batasan pada tipe apa yang harus diterapkan agar dapat digunakan sebagai parameter tipe.