“ Where T: class, new ()” หมายถึงอะไร


คำตอบ:


329

นั่นคือข้อ จำกัด Tในพารามิเตอร์ทั่วไป มันจะต้องเป็นclass(ประเภทการอ้างอิง) และจะต้องมีการกำหนดค่าเริ่มต้นน้อยพารามิเตอร์สาธารณะ

นั่นหมายความว่าTไม่สามารถจะเป็นint, float, double, DateTimeหรืออื่น ๆstruct(ประเภทค่า)

มันอาจจะเป็นstringหรือประเภทอ้างอิงที่กำหนดเองอื่น ๆ ตราบใดที่มันมีค่าเริ่มต้นหรือตัวสร้างพารามิเตอร์น้อย


5
เพียงชี้แจงให้ชัดเจนหากคุณไม่มีส่วนคำสั่งคลาสเป็นส่วนหนึ่งของตำแหน่งที่ T ... ดังนั้นจึงปลอดภัยที่จะใช้ int, float, double และอื่น ๆ
AboutDev

1
@AboutDev ถูกต้องคุณไม่จำเป็นต้องใส่ข้อ จำกัด ในพารามิเตอร์ประเภททั่วไปของคุณ แต่ถ้าคุณกำลังสร้างประเภททั่วไปที่คาดว่าจะทำงานกับประเภทการอ้างอิงหรือค่าเท่านั้นคุณควรระบุ โดยไม่มีข้อ จำกัด คุณสามารถคาดหวังประเภทการอ้างอิง (คลาส) หรือประเภทค่า (struct (int, float, double ... ))
NerdFury

1
แล้ว T: [ชื่ออินเตอร์เฟส], new ()? คุณยังต้องการตัวสร้างที่ไม่มีพารามิเตอร์หรือไม่?
Vince Tino

3
เพื่อชี้แจงความคิดเห็นของจัสตินคอนสตรัคเตอร์ว่างเปล่าไม่มีคำสั่ง (เช่นคอนสตรัคเตอร์เริ่มต้น) ในขณะที่คอนสตรัคเตอร์แบบไม่มีพารามิเตอร์อาจมีคำสั่ง (เช่นการเริ่มต้นรายการ)
DharmaTurtle

@VinceTino: new()ระบุอย่างแม่นยำ "ต้องมีตัวสร้างพารามิเตอร์แบบไม่มีพารามิเตอร์สาธารณะ"
Flater

162

นั่นเป็นข้อ จำกัด ประเภททั่วไป ในกรณีของคุณมีสองคน:

where T : class

หมายความว่าประเภทนั้นTจะต้องเป็นประเภทอ้างอิง (ไม่ใช่ประเภทค่า)

where T : new()

หมายความว่าประเภทTต้องมีตัวสร้างพารามิเตอร์น้อย การมีข้อ จำกัด นี้จะช่วยให้คุณทำสิ่งที่ต้องการT field = new T();ในรหัสของคุณซึ่งคุณจะไม่สามารถทำได้

จากนั้นคุณทั้งสองรวมกันโดยใช้เครื่องหมายจุลภาคเพื่อรับ:

where T : class, new()

คะแนนที่ดีสำหรับที่สองและสามเพียงเพื่อเพิ่มข้อมูลฉันคิดว่าจุดที่สองมีประโยชน์เมื่อทำการสะท้อนในประเภททั่วไป เช่น. T t = new T (); t.GetType (). GetProperty ("ID") SetValue (t, uniqueId, null);
Jerry Liang

1
ฉันเชื่อว่ามันซ้ำซ้อนที่จะบอกตำแหน่งที่ T: class, new () เนื่องจาก new () หมายถึงคลาสแล้วเพราะ structs ไม่สามารถมี Constructor เริ่มต้นได้
DharmaTurtle

@DharmaTurtle "structs ไม่สามารถมีตัวสร้างพารามิเตอร์ที่ไม่มีพารามิเตอร์อย่างชัดเจน" ไม่ได้หมายความว่าพวกมันไม่มีมันบอกว่าคุณไม่สามารถกำหนดได้ แหล่งที่มา: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
rustem

121

โดยที่ T: struct

อาร์กิวเมนต์ type ต้องเป็นประเภทค่า ชนิดของค่าใด ๆ ยกเว้น Nullable สามารถระบุได้ ดูการใช้ประเภทที่มีค่า Nullable (คู่มือการเขียนโปรแกรม C #) สำหรับข้อมูลเพิ่มเติม

โดยที่ T: class

อาร์กิวเมนต์ type ต้องเป็นชนิดการอ้างอิงรวมถึงคลาส, อินเตอร์เฟส, ผู้รับมอบสิทธิ์หรือชนิดอาร์เรย์ (ดูหมายเหตุด้านล่าง)

โดยที่ T: new () อาร์กิวเมนต์ type ต้องมีตัวสร้างพารามิเตอร์แบบไม่มีพารามิเตอร์สาธารณะ เมื่อใช้ร่วมกับข้อ จำกัด อื่น ๆ จะต้องระบุข้อ จำกัด ใหม่ () ล่าสุด

โดยที่ T: [ชื่อคลาสฐาน]

อาร์กิวเมนต์ type ต้องเป็นหรือสืบทอดมาจากคลาสฐานที่ระบุ

โดยที่ T: [ชื่ออินเตอร์เฟส]

อาร์กิวเมนต์ type ต้องเป็นหรือใช้อินเตอร์เฟสที่ระบุ สามารถระบุข้อ จำกัด หลาย ๆ อินเตอร์เฟสได้ อินเทอร์เฟซที่ จำกัด ยังสามารถทั่วไป

โดยที่ T: U

อาร์กิวเมนต์ type ที่ระบุสำหรับ T ต้องเป็นหรือสืบทอดมาจากอาร์กิวเมนต์ที่ให้สำหรับ U ซึ่งเรียกว่าข้อ จำกัด ประเภทเปล่า


23
นี้เป็นประโยชน์ แต่เชื่อมโยงไปยังแหล่งที่มา
Skean

26

classและnewมี 2 ข้อ จำกัด Tในพารามิเตอร์ประเภททั่วไป
พวกเขามั่นใจตามลำดับ:

class

อาร์กิวเมนต์ type ต้องเป็นชนิดการอ้างอิง สิ่งนี้ใช้ได้กับคลาส, อินเทอร์เฟซ, ตัวแทนหรือประเภทอาร์เรย์

new

อาร์กิวเมนต์ type ต้องมีตัวสร้างพารามิเตอร์แบบไม่มีพารามิเตอร์สาธารณะ เมื่อใช้ร่วมกับข้อ จำกัด อื่น ๆ จะต้องระบุข้อ จำกัด ใหม่ () ล่าสุด

การรวมกันของพวกเขาหมายความว่าประเภทTจะต้องเป็นประเภทอ้างอิง (ไม่สามารถเป็นประเภทค่า ) และต้องมีตัวสร้างแบบพารามิเตอร์

ตัวอย่าง:

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
การสาธิตที่ดี ขอบคุณ
Subhan Ali

15

() ใหม่:การกําหนดใหม่ () จำกัด วิธีการพิมพ์ T ต้องใช้นวกรรมิก parameterless ดังนั้นวัตถุที่สามารถ instantiated จากมัน - ดูการก่อสร้างเริ่มต้น

class:หมายถึง T ต้องเป็นประเภทอ้างอิงดังนั้นจึงไม่สามารถเป็น int, float, Double, DateTime หรือ struct อื่น ๆ (ประเภทค่า)

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

นั่นหมายความว่าประเภทนั้นTจะต้องเป็นคลาสและมีตัวสร้างที่ไม่มีอาร์กิวเมนต์ใด ๆ

ตัวอย่างเช่นคุณต้องสามารถทำสิ่งนี้:

T t = new T();

1
ไม่ใช่แค่ตัวสร้าง แต่เป็นตัวสร้างที่ไม่มีอาร์กิวเมนต์
NerdFury

@NerdFury: ขอบคุณ นั่นเป็นบิตที่สำคัญ การแก้ไข
Evan Mulawski

5

โดยที่ (อ้างอิง C #)

ข้อ จำกัด ใหม่ () ให้คอมไพเลอร์ทราบว่าอาร์กิวเมนต์ประเภทใด ๆ ที่ระบุต้องมีพารามิเตอร์ที่สามารถเข้าถึงได้ - หรือค่าเริ่มต้น - คอนสตรัคเตอร์

ดังนั้นควรจะTต้องเป็นคลาสและมีตัวสร้างพารามิเตอร์ที่ไม่สามารถเข้าถึงได้ - หรือตัวสร้างเริ่มต้น


4

สิ่งที่เกิดขึ้นหลังจาก "Where" เป็นข้อ จำกัด ของประเภททั่วไป T ที่คุณประกาศดังนั้น:

  • classหมายถึงว่า T ควรเป็นคลาสและไม่ใช่ประเภทของค่าหรือโครงสร้าง

  • ใหม่ ()ระบุว่าคลาส T ควรมีคอนสตรัคเตอร์เริ่มต้นที่ไม่มีพารามิเตอร์สาธารณะ


1

มันเรียกว่า 'ข้อ จำกัด ' ในพารามิเตอร์ทั่วไป T ซึ่งหมายความว่า T จะต้องเป็นประเภทการอ้างอิง (คลาส) และต้องมีตัวสร้างค่าเริ่มต้นสาธารณะ


1

นี่เป็นส่วนหนึ่งของกลไก Generics โดยที่ where คำสำคัญเพิ่มข้อ จำกัด ประเภทที่ต้องดำเนินการเพื่อใช้เป็นพารามิเตอร์ประเภท


0

เมื่อใช้คลาสในข้อ จำกัด หมายความว่าคุณสามารถใช้ประเภทการอ้างอิงได้เท่านั้นสิ่งอื่นที่จะเพิ่มคือเมื่อใช้ข้อ จำกัดใหม่ ()จะต้องเป็นสิ่งสุดท้ายที่คุณเขียนในข้อกำหนดของข้อ จำกัด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.