C # สร้างใหม่ T ()


159

คุณสามารถเห็นสิ่งที่ฉันพยายาม (แต่ล้มเหลว) จะทำอย่างไรกับรหัสต่อไปนี้:

protected T GetObject()
{
    return new T();
}

ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชมอย่างมาก.

แก้ไข:

บริบทมีดังนี้ ฉันเล่นกับคลาสคอนโทรลเลอร์ที่กำหนดเองเพื่อให้คอนโทรลเลอร์ทั้งหมดได้มาด้วยวิธีมาตรฐาน ดังนั้นในบริบทฉันต้องการสร้างอินสแตนซ์ใหม่ของวัตถุประเภทตัวควบคุม ดังนั้นในช่วงเวลาของการเขียนมันเป็นสิ่งที่ชอบ:

public class GenericController<T> : Controller
{
    ...

    protected T GetObject()
    {
        return (T)Activator.CreateInstance(ObjectType);
    }        

    public ActionResult Create()
    {
        var obj = GetObject()

        return View(obj);
    }

ดังนั้นฉันจึงตัดสินใจว่าการสะท้อนนั้นง่ายที่สุดที่นี่ ฉันเห็นด้วยอย่างแน่นอนเมื่อได้รับข้อความเริ่มต้นของคำถามคำตอบที่เหมาะสมที่สุดในการทำเครื่องหมายว่าถูกต้องคือคำที่ใช้ข้อ จำกัด ใหม่ () ฉันได้แก้ไขแล้ว


27
ไม่ฉันไม่เห็นสิ่งที่คุณพยายามและล้มเหลวในการทำ ฉันเห็นโค้ดบางส่วนที่อาจเป็นส่วนหนึ่งของโปรแกรมทำงานโดยไม่มีบริบทไม่มีข้อความแสดงข้อผิดพลาดและไม่มีคำอธิบาย
Ben Voigt

17
แย่แล้วฉันเกลียดเมื่อเลือกคำตอบที่ผิด!
David Heffernan

คำตอบ:


409

ดูข้อ จำกัด ใหม่

public class MyClass<T> where T : new()
{
    protected T GetObject()
    {
        return new T();
    }
}

Tอาจเป็นคลาสที่ไม่มีตัวสร้างเริ่มต้น: ในกรณีนี้new T()จะเป็นคำสั่งที่ไม่ถูกต้อง new()จำกัด กล่าวว่าTจะต้องมีการสร้างเริ่มต้นซึ่งจะทำให้new T()ถูกต้องตามกฎหมาย

คุณสามารถใช้ข้อ จำกัด เดียวกันกับวิธีทั่วไป:

public static T GetObject<T>() where T : new()
{
    return new T();
}

หากคุณต้องการส่งพารามิเตอร์:

protected T GetObject(params object[] args)
{
    return (T)Activator.CreateInstance(typeof(T), args);
}

2
ขอบคุณเพื่อน - ฉันดีใจที่ได้เรียนรู้ในวันนี้ ด้วยบริบทของวิธีการของฉันฉันได้ไปหาวิธีแก้ปัญหาการสะท้อนกลับ ไชโย!
Hanshan

8
@nulliusinverba - อืม ... มันคงจะดีถ้าคุณแสดงบริบทของวิธีการของคุณในคำถาม
Alex Aza

1
@nulliusinverba - คุณไม่ได้แสดงในคำถามที่คุณต้องการพารามิเตอร์
Alex Aza

1
@ Alex - เมื่อผมอ่านคำถามของเขาผมถือว่าเขาไม่ต้องการพารามิเตอร์: S Up-คะแนนสำหรับคุณ แต่ :)
Phill

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


29

อีกวิธีคือใช้การสะท้อน:

protected T GetObject<T>(Type[] signature, object[] args)
{
    return (T)typeof(T).GetConstructor(signature).Invoke(args);
}

ขอบคุณเพื่อน - ฉันไปกับวิธีแก้ปัญหานี้ให้บริบทของวิธีการ
Hanshan

22
เช่นเดียวกับ FYI ซึ่งสามารถเขียนเป็น Activator.CreateInstance (typeof (T), Signature, args); ดูmsdn.microsoft.com/en-us/library/4b0ww1we.aspxสำหรับรายละเอียดเพิ่มเติม
Chris Baxter

@Calgary Coder: การใช้ลายเซ็นประเภท [] คืออะไรคุณสามารถโทร CreateInstance ด้วย params โดยตรงโดยไม่ต้องระบุลายเซ็นอย่างชัดเจน ในทั้งสองกรณีคุณจะได้รับ MissingMethodException หากไม่มี Constructor ที่ตรงกัน
Boris B.

4
แม้ว่านี่จะเป็นคำตอบที่ดีที่สุดสำหรับคุณ แต่ก็ไม่ใช่คำตอบที่ดีที่สุดสำหรับชุมชน คนที่มองหาคำถามนี้กำลังมองหาคำตอบจากด้านล่างจริงๆ
กับดัก

และบริบทนั้นคืออะไร? โปรดเพิ่มลงในคำถามเดิม
James

18

เพียงเสร็จสิ้นทางออกที่ดีที่สุดที่นี่มักจะต้องมีการโต้แย้งฟังก์ชั่นโรงงาน:

T GetObject<T>(Func<T> factory)
{  return factory(); }

และเรียกสิ่งนี้:

string s = GetObject(() => "result");

คุณสามารถใช้สิ่งนั้นเพื่อต้องการหรือใช้พารามิเตอร์ที่มีอยู่หากจำเป็น


16

จำกัด ใหม่จะปรับ แต่ถ้าคุณต้องการ T เป็นประเภทค่าเกินไปใช้นี้

protected T GetObject() {
    if (typeof(T).IsValueType || typeof(T) == typeof(string)) {
        return default(T);
    } else {
       return (T)Activator.CreateInstance(typeof(T));
    }
}

7

เนื่องจากสิ่งนี้ถูกติดแท็ก C # 4 ด้วยเฟรมเวิร์ก sourece แบบเปิดImpromptuInterefaceมันจะใช้ dlr เพื่อเรียกใช้ตัวสร้างมันจะเร็วกว่า Activator อย่างมีนัยสำคัญเมื่อตัวสร้างของคุณมีข้อโต้แย้ง อย่างไรก็ตามข้อดีหลักคือมันจะจัดการตัวสร้างด้วยพารามิเตอร์ทางเลือก C # 4.0 อย่างถูกต้องสิ่งที่ Activator จะไม่ทำ

protected T GetObject(params object[] args)
{
    return (T)Impromptu.InvokeConstructor(typeof(T), args);
}

4

เพื่อรับนี้ฉันลองรหัสต่อไปนี้:

  protected T GetObject<T>()
    {
        T obj = default(T);
        obj =Activator.CreateInstance<T>();
        return obj ;
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.