#c# #linq #generics #reflection #collections
#c# #linq #общие #отражение #Коллекции
Вопрос:
От параметра к свойству?
public class ConcatenateListTMember
{
public static void Test()
{
var someList = new List<AnyClass>();
someList.Add(new AnyClass("value1"));
someList.Add(new AnyClass("value2"));
Console.WriteLine(Concatenate(someList, "SomeProperty"));
Console.ReadLine();
}
static string Concatenate<T>(List<T> list, string specifiedPropertyOfT)
{
string output = String.Empty;
// TODO: Somehow concatenate all the specified property elements in the list?
return output;
}
}
internal class AnyClass
{
public AnyClass(string someProperty)
{
SomeProperty = someProperty;
}
public string SomeProperty { get; set; }
}
Как можно реализовать универсальный метод в этом примере кода?
- Пожалуйста, обратите внимание, что
specifiedPropertyOfT
это не обязательно должна быть строка, если та же цель может быть достигнута с использованием другого типа. - В идеале отражение не требовалось бы 🙂
Ответ №1:
Я думаю, вы ищете новые перегрузки string.Join
в .NET 4, которые позволили бы:
IEnumerable<AnyClass> sequence = ...;
string joined = string.Join(",", sequence.Select(x => x.SomeProperty));
Если вы не можете использовать лямбда-выражение для выражения свойства — например, потому что это должно быть сделано во время выполнения — тогда вам придется использовать отражение.
Обратите внимание, что селектор в Select
не должен возвращать строки — String.Join
будет вызывать ToString
любые нестроковые значения.
Ответ №2:
Еще лучше — метод расширения:
static string Concatenate<T>(this IEnumerable<T> list, Func<T,string> func)
{
return String.Join("",list.Select(func));
}
Использование:
someList.Concatenate(i => i.SomeProperty);
Живой пример: http://rextester.com/runcode?code=LRA78268
Ответ №3:
Попробуйте что-то вроде этого. Я создал метод расширения для IEnumerable:
public static class Extension
{
public static string ConcatinateString<T>(this IEnumerable<T> collection, Func<T, string> GetValue)
{
StringBuilder sb = new StringBuilder();
foreach (var item in collection)
{
sb.Append(GetValue(item));
}
return sb.ToString();
}
}
Тогда назовите это так, вы бы использовали что-то вроде этого:
var values = new List<TestClass>
{
new TestClass(){Name="John",Comment="Hello"},
new TestClass(){Name="Smith", Comment="Word"}
};
string s = values.ConcatinateString((x => x.Name));
string v = values.ConcatinateString((x => x.Comment));
В этом примере s = "JohnSmith"
и v = "HelloWord"
. Функция Func() дает вам гибкость. По сути, вы указываете функции, куда идти, чтобы получить строку для конкатенации. Я также использовал StringBuilder на случай, если вы работаете с длинными коллекциями.