Как я преобразовываю IEnumerable в пользовательский тип в C#?

Некоторые мои лучшие расширения метода (у меня есть много!):

public static T ToEnum<T>(this string str) where T : struct
{
    return (T)Enum.Parse(typeof(T), str);
}

//DayOfWeek sunday =  "Sunday".ToEnum<DayOfWeek>();

public static string ToString<T>(this IEnumerable<T> collection, string separator)
{
    return ToString(collection, t => t.ToString(), separator);
}

public static string ToString<T>(this IEnumerable<T> collection, Func<T, string> stringElement, string separator)
{
    StringBuilder sb = new StringBuilder();
    foreach (var item in collection)
    {
        sb.Append(stringElement(item));
        sb.Append(separator);
    }
    return sb.ToString(0, Math.Max(0, sb.Length - separator.Length));  // quita el ultimo separador
}

//new []{1,2,3}.ToString(i=>i*2, ", ")  --> "2, 4, 6"

кроме того, следующие предназначены, чтобы быть в состоянии продолжиться в той же строке почти в любой ситуации, не объявляя новые переменные и затем удаляя состояние:

public static R Map<T, R>(this T t, Func<T, R> func)
{
    return func(t);
}

ExpensiveFindWally().Map(wally=>wally.FirstName + " " + wally.LastName)

public static R TryCC<T, R>(this T t, Func<T, R> func)
    where T : class
    where R : class
{
    if (t == null) return null;
    return func(t);
}

public static R? TryCS<T, R>(this T t, Func<T, R> func)
    where T : class
    where R : struct
{
    if (t == null) return null;
    return func(t);
}

public static R? TryCS<T, R>(this T t, Func<T, R?> func)
    where T : class
    where R : struct
{
    if (t == null) return null;
    return func(t);
}

public static R TrySC<T, R>(this T? t, Func<T, R> func)
    where T : struct
    where R : class
{
    if (t == null) return null;
    return func(t.Value);
}

public static R? TrySS<T, R>(this T? t, Func<T, R> func)
    where T : struct
    where R : struct
{
    if (t == null) return null;
    return func(t.Value);
}

public static R? TrySS<T, R>(this T? t, Func<T, R?> func)
    where T : struct
    where R : struct
{
    if (t == null) return null;
    return func(t.Value);
}

//int? bossNameLength =  Departament.Boss.TryCC(b=>b.Name).TryCS(s=>s.Length);


public static T ThrowIfNullS<T>(this T? t, string mensaje)
    where T : struct
{
    if (t == null)
        throw new NullReferenceException(mensaje);
    return t.Value;
}

public static T ThrowIfNullC<T>(this T t, string mensaje)
    where T : class
{
    if (t == null)
        throw new NullReferenceException(mensaje);
    return t;
}

public static T Do<T>(this T t, Action<T> action)
{
    action(t);
    return t;
}

//Button b = new Button{Content = "Click"}.Do(b=>Canvas.SetColumn(b,2));

public static T TryDo<T>(this T t, Action<T> action) where T : class
{
    if (t != null)
        action(t);
    return t;
}

public static T? TryDoS<T>(this T? t, Action<T> action) where T : struct
{
    if (t != null)
        action(t.Value);
    return t;
}

Hope это не похоже на прибытие из Марса:)

5
задан Tony D 13 July 2009 в 20:46
поделиться

10 ответов

Если ваш тип коллекции реализует IList (чтобы иметь возможность Add () к нему), вы можете написать метод расширения:

public static Extensions
{
    public static TColl ToTypedCollection<TColl, T>(this IEnumerable ien)
        where TColl : IList<T>, new()
    {
        TColl collection = new TColl();

        foreach (var item in ien)
        {
            collection.Add((T) item);
        }

        return collection;
    }
}
6
ответ дан 14 December 2019 в 04:45
поделиться

Нет, нет. Когда вы используете операторы запроса, они не используют экземпляры исходной коллекции для создания перечисления. Скорее, он использует частные реализации (возможно, анонимные, а возможно, и нет) для обеспечения этой функциональности.

Если вы хотите, чтобы это было в вашей исходной коллекции, у вас должен быть конструктор типа, который принимает IEnumerable (или все, что хранится в вашей коллекции, если это определенно), а затем передать запрос конструктору.

Затем вы можете использовать это для создания метода расширения для IEnumerable с именем В , который примет IEnumerable , а затем передаст его конструктору вашего типа и вернет его.

1
ответ дан 14 December 2019 в 04:45
поделиться

Нет. Вы можете следовать шаблону, установленному методами расширения ToList и ToDictionary - написать аналогичный метод расширения для загрузки собственного типа коллекции из IEnumerable.

1
ответ дан 14 December 2019 в 04:45
поделиться

Вы можете написать свой собственный экземпляр IComparer, чтобы иметь возможность сортировать ваш собственный сбор.

Грубая сила: вы можете пройти через IEnumerable и сбросить каждый элемент обратно в новый экземпляр вашего пользовательского сборник.

0
ответ дан 14 December 2019 в 04:45
поделиться

Вы можете инициализировать список с помощью IEnumerable:

Если items имеет тип IEnumerable, вы можете создать такой список:

var list = new List<string>(items);

или просто вызвать items.ToList () :

var list = items.ToList();
0
ответ дан 14 December 2019 в 04:45
поделиться

Какие интерфейсы реализует ваша настраиваемая коллекция?

Если это IList, вы могли бы использовать .ToList () в IEnumerable. Если это IDictionary, вы сможете использовать .ToDictionary () в IEnumerable И т. Д.

, чтобы сделать из него что-то более подходящее для вас.

Вы можете написать метод расширения для IEnumerable для .ToMyCollection (), если нет ничего похожего.

0
ответ дан 14 December 2019 в 04:45
поделиться

Перечислимые объекты и коллекции - довольно разные звери.

Перечисления позволяют, ну, перечислять, в то время как коллекции имеют основанные на индексе средства доступа, свойство Count и тому подобное. Чтобы создать коллекцию, вам действительно нужно будет перечислить IEnumerable. Типичные коллекции, такие как List , будут иметь конструктор, принимающий IEnumerable. Тем не менее, подсчет будет выполнен.

0
ответ дан 14 December 2019 в 04:45
поделиться

Если вы посмотрите в класс System.Linq.Enumerable, есть несколько методов расширения, которые позволят вам преобразовать ваш тип IEnumerable либо в массив, либо в ToList

var myEnumerable = this.GetEnumerator();

var array = myEnumerable.ToArray();
var list myEnumerable.ToList();

. Вы можете следовать этому подходу. и создайте собственный метод расширения, который будет преобразован в вашу пользовательскую коллекцию

public static CustomCollection<TSource> ToCustomCollection<TSource>(this IEnumerable<TSource> source);
0
ответ дан 14 December 2019 в 04:45
поделиться

Вам действительно нужен собственный тип коллекции? Похоже, все, что вы хотите с этим сделать, обеспечивается существующими типами общих коллекций, и, возможно, вам просто нужно добавить метод расширения или для них.

0
ответ дан 14 December 2019 в 04:45
поделиться

LINQ хорош, потому что он рассматривает исходные коллекции, как этот, как неизменяемые - он не изменяет их. Использование методов расширения просто перечисляет их в указанном вами альтернативном порядке - вы не создаете НОВЫЙ настраиваемый список таким образом.

Я бы предложил два варианта:

  1. Создайте новый список самостоятельно на основе результатов вашего LINQ-ing.
  2. Внедрите возможность сортировки в свою настраиваемую коллекцию (или используйте удобную сортируемую общую коллекцию в качестве основы), чтобы она могла выполнять сортировку на месте.
0
ответ дан 14 December 2019 в 04:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: