Лучший способ преобразовать IList или IEnumerable в массив


99

У меня есть запрос HQL, который может генерировать либо список результатов, либо IEnumerable результатов.

Однако я хочу, чтобы он возвращал массив объекта, который я выбираю, что было бы лучшим способом для этого? Я могу либо перечислить его и построить массив, либо использовать CopyTo () для определенного массива.

Есть ли способ лучше? Я пошел с CopyTo-подходом.


4
У кого-нибудь есть решение без Linq?
Bitterblue

Ответы:


167

Какую версию .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
Нет, есть только один способ расширения. (Это не в самом интерфейсе.)
Джон Скит,

3
@Shimmy: Да, есть ... помимо всего прочего, он сообщает компилятору, какой массив ожидать! Если вы хотите object[]просто использовать Cast<object>. Неуниверсальный IEnumerableне имеет ToArrayметода расширения, поэтому вы не можете просто вызвать foo.ToArray<object>или что-то в этом роде.
Джон Скит

22
Метод ToArrayрасширения находится в System.Linqпространстве имен, подумал, что было бы полезно знать :).
Томас Янссон

1
@Alexander: Нет, если возвращаемое значение действительно не является подходящим массивом.
Джон Скит

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

хех - я на самом деле вроде как это: если enumerable на самом деле является массивом, вы пропускаете новое выделение / копирование для шагов в ToArray()вызове (через внутренний Bufferкласс) ... хотя, если кто-то ожидал "стандартного" "копировать поведение, они были бы очень удивлены.
JerKimball 06

@Chris: Потому что меня вдохновила сигнатура метода ToArray () в System.Linq. msdn.microsoft.com/en-us/library/bb298736.aspx
Philippe

Для дополнительной нелепости реализация этого метода должна называтьIEnumerable.ToArray()
The Muffin Man

2

Если у вас нет Linq, я решил это следующим образом:

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

        iList.CopyTo(result, 0);

        return result;
    }

Надеюсь, поможет

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.