วิธีที่ดีที่สุดในการแปลง IList หรือ IEnumerable เป็น Array


101

ฉันมีแบบสอบถาม HQL ที่สามารถสร้างรายการผลลัพธ์หรือ IE ไม่สามารถระบุผลลัพธ์ได้

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

มีวิธีไหนที่ดีกว่านี้ไหม? ฉันใช้วิธี CopyTo-approach


4
ใครมีวิธีแก้ปัญหาโดยไม่ต้อง Linq?
Bitterblue

คำตอบ:


168

คุณกำลังใช้. NET เวอร์ชันใดอยู่ ถ้าเป็น. NET 3.5 ฉันจะโทรหาToArray()และจัดการให้เสร็จ

หากคุณมีเฉพาะ IEnumerable ที่ไม่ใช่ทั่วไปให้ทำดังนี้:

IEnumerable query = ...;
MyEntityType[] array = query.Cast<MyEntityType>().ToArray();

หากคุณไม่ทราบประเภทภายในเมธอดนั้น แต่ผู้เรียกของเมธอดรู้จักให้กำหนดวิธีการทั่วไปแล้วลองทำดังนี้

public static void T[] PerformQuery<T>()
{
    IEnumerable query = ...;
    T[] array = query.Cast<T>().ToArray();
    return array;
}

เป็น 3.5 แต่ IQuery ไม่มี ToArray หรือไม่ IEnumerable หรือ IList เท่าที่ฉันบอกได้?
jishi

2
ไม่ - มีวิธีการขยายเพียงวิธีเดียว (มันไม่ได้อยู่ในส่วนต่อประสาน)
Jon Skeet

3
@Shimmy: ใช่มี ... นอกเหนือจากอย่างอื่นมันบอกคอมไพเลอร์ว่าจะคาดหวังอาร์เรย์แบบไหน! หากคุณต้องการเพียงการใช้งานเพียงแค่object[] Cast<object>nongeneric IEnumerableไม่มีToArrayวิธีการขยายดังนั้นคุณจึงไม่สามารถเรียกfoo.ToArray<object>หรืออะไรทำนองนั้นได้
Jon Skeet

23
ToArrayวิธีขยายเป็นในSystem.Linqnamespace คิดที่อาจจะดีที่จะรู้ :)
Tomas Jansson

1
@ อเล็กซานเดอร์: ไม่เว้นแต่ว่าค่าที่ส่งคืนจะเป็นอาร์เรย์ที่เหมาะสม
Jon Skeet

47

ใส่สิ่งต่อไปนี้ในไฟล์. cs ของคุณ:

using System.Linq;

จากนั้นคุณจะสามารถใช้วิธีการขยายต่อไปนี้จาก System.Linq.Enumerable:

public static TSource[] ToArray<TSource>(this System.Collections.Generic.IEnumerable<TSource> source)

ได้แก่

IEnumerable<object> query = ...;
object[] bob = query.ToArray();

อ่า ... โครงการทดสอบหน่วยไม่รวม linq ตามค่าเริ่มต้น ขอบคุณ!
zsf222

6

ฉันรู้สึกอยากจะคิดค้นล้อใหม่ ...

public static T[] ConvertToArray<T>(this IEnumerable<T> enumerable)
{
    if (enumerable == null)
        throw new ArgumentNullException("enumerable");

    return enumerable as T[] ?? enumerable.ToArray();
}

คุณสามารถอธิบายคำตอบของคุณและสิ่งที่คุณหมายถึงเมื่อคุณรู้สึกว่าคุณกำลังคิดค้นล้อใหม่หรือไม่?
ChrisCamp

เฮ้ - ฉันเป็นแบบนี้จริง ๆ ในกรณีที่ไม่สามารถระบุได้ว่าเป็นอาร์เรย์จริงๆคุณกำลังข้ามการจัดสรร / คัดลอกใหม่ไปยังขั้นตอนในการToArray()โทร (ผ่านBufferคลาสภายใน) ... แม้ว่าใครจะคาดหวัง "มาตรฐาน "พฤติกรรมการคัดลอกพวกเขาค่อนข้างประหลาดใจ
JerKimball

@Chris: เพราะฉันได้รับแรงบันดาลใจจากลายเซ็นของ ToArray () method ใน System.Linq msdn.microsoft.com/en-us/library/bb298736.aspx
Philippe Matray

สำหรับความไร้สาระที่เพิ่มขึ้นควรเรียกใช้วิธีนี้IEnumerable.ToArray()
The Muffin Man

3

ในกรณีที่คุณไม่มี Linq ฉันแก้ไขด้วยวิธีต่อไปนี้:

    private T[] GetArray<T>(IList<T> iList) where T: new()
    {
        var result = new T[iList.Count];

        iList.CopyTo(result, 0);

        return result;
    }

หวังว่าจะช่วยได้

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