Как получить значение из коллекции IEnumerable, используя ее ключ?

У меня есть коллекция IEnumerable, например следующая

IEnumerable<Customer> items = new Customer[] 
{ 
     new Customer { Name = "test1", Id = 999 }, 
     new Customer { Name = "test2", Id = 989 } 
};

Я хочу получить значение, используя ключ Id

Я пытался следовать

public int GetValue(IEnumerable<T> items,string propertyName)
{
      for (int i = 0; i < items.Count(); i++)
      {
           (typeof(T).GetType().GetProperty(propertyName).GetValue(typeof(T), null));
           // I will pass propertyName as Id and want all Id propperty values 
           // from items collection one by one.
      }
}

person Neo    schedule 24.08.2015    source источник
comment
Почему бы вам просто не использовать метод Select? Это тоже типобезопасно.   -  person Ufuk Hacıoğulları    schedule 24.08.2015
comment
items.Select(x=>x.Id) сделал бы это. чего вы пытаетесь достичь?   -  person Sriram Sakthivel    schedule 24.08.2015
comment
dynamiclinq.codeplex.com   -  person Eser    schedule 24.08.2015
comment
Если вы хотите сделать это общим способом, вы можете указать селектор Func‹T, bool› (предикат) для своего метода вместо аргумента propertyName, а затем использовать его в предложении linq where. То же самое с тем, что вам нужно выбрать. Если это весь элемент T, вам не нужен конкретный select, но если вам нужно только определенное свойство, передайте другую функцию выбора (типа Func<T, whatever type>)   -  person kha    schedule 24.08.2015


Ответы (6)


// Я передам propertyName как Id и хочу, чтобы все значения свойства Id

// из коллекции элементов по одному.

Если я правильно тебя понял

public static IEnumerable<object> GetValues<T>(IEnumerable<T> items, string propertyName)
{
    Type type = typeof(T);
    var prop = type.GetProperty(propertyName);
    foreach (var item in items)
        yield return prop.GetValue(item, null);
}
person Eser    schedule 24.08.2015

Если вы хотите получить имя Customer из коллекции по его Id:

public string GetCustomerName(IEnumerable<Customer> customers, int id)
{
    return customers.First(c => c.Id == id).Name;
}
person w.b    schedule 24.08.2015
comment
Я не получаю c.Id я получаю c. Equals,GetHashCode,GetType,ToString - person Neo; 24.08.2015
comment
вероятно, потому что вы запрашиваете IEnumerable<object> , а не IEnumerable<Customer>, попробуйте что-то вроде customers.OfType<Customer>() - person w.b; 24.08.2015
comment
@Neo, я думаю, тебе нужно включить использование System.Linq. У меня была такая же проблема, сработало после того, как я включил использование System.Linq - person Arvind Krmar; 26.11.2020

Используя LINQ, вы можете получить все имена (значения) клиентов, имеющие определенный идентификатор (ключ), следующим образом:

var valuesList = items.Where(x => x.Id == 1).Select(v => v.Name).ToList();

Для одного имени клиента вы можете сделать это:

var singleName = items.FirstOrDefault(x => x.Id == 1)?.Name;

Очевидно, Id может быть 1, 2 или любым другим.

Редактировать:

Я рекомендую вам List<Customer> вместо Customer[]

So,

var items = new List<Customer> 
{ 
     new Customer { Name = "test1", Id = 999 }, 
     new Customer { Name = "test2", Id = 989 } 
};
person NASSER    schedule 24.08.2015
comment
Я не получаю x.Id я получаю x. Equals,GetHashCode,GetType,ToString - person Neo; 24.08.2015
comment
Использовать приведение как (Customer)x.Id. - person NASSER; 24.08.2015
comment
@Neo Если вы будете использовать List<Customer>, то теперь вам потребуется любое приведение, в противном случае требуется приведение для анонимного типа. - person NASSER; 24.08.2015
comment
не могли бы вы заглянуть в один из моих вопрос связан с этим? - person Moeez; 16.04.2019

Просто используйте LINQ для достижения того, что вы хотите сделать. если вы хотите получить определенное значение, вы можете использовать where следующим образом:

public Customer GetCustomerById(IEnumerable<Customer> items,int key)
{
    return items.Where(x=>x.id==key)
   .Select(x =>x.Name)
   .First(); 
}

это позволит получить клиента, который соответствует определенному идентификатору.

person Nadeem Khoury    schedule 24.08.2015
comment
не могли бы вы заглянуть в один из моих вопрос связан с этим? - person Moeez; 16.04.2019

Вы хотите повторно искать вещи после создания списка? Если это так, вы можете подумать о создании словаря для поиска, например:

IEnumerable<Customer> items = new Customer[]
{
    new Customer {Name = "test1", Id = 999},
    new Customer {Name = "test2", Id = 989}
};

var lookup = items.ToDictionary(itemKeySelector => itemKeySelector.Id);

var result = lookup[989];

Console.WriteLine(result.Name); // Prints "test2".

Я предполагаю, что вы не создаете коллекцию в первую очередь - если бы у вас был контроль над созданием исходной коллекции, вы могли бы использовать словарь в первую очередь.

person Matthew Watson    schedule 24.08.2015

person    schedule
comment
Здравствуйте Игорь! Объясните в одном-двух предложениях, что вы сделали в коде, чтобы было понятнее. - person Pluto; 27.05.2020
comment
Точка зрения @Pluto всегда является хорошей практикой, но она особенно важна для этих старых вопросов с установленными ответами. Зачем использовать этот подход по сравнению с другими пятью ответами? - person Jeremy Caney; 28.05.2020
comment
Привет, я думаю, что это так просто и не нужно комментировать, на самом деле вы можете убрать var и ввести просто TextBox [] somename = panel1.Controls.Oftype‹TextBox›().Toarray(); это вы просто создаете коллекцию всех элементов управления, расположенных на панели 1, с типом, TextBox› после того, как у вас есть постоянная коллекция (то есть индекс будет таким же, и вы можете управлять этим для записи/записи данных) - person Igor; 02.06.2020
comment
индекс будет одинаковым все время, после array() у вас будет постоянный индекс. для чтения или записи вам не нужно знать имена текстовых полей, просто создайте алгоритм для получения информации и записи, чтение будет использовать тот же индекс. - person Igor; 02.06.2020