Обновить элемент в IEnumerable
мне нужно обновить значение в списке IEnumerable.
вот краткий пример IEnumerable:
IEnumerable<string> allsubdirs = new List<string>() { "a", "b", "c" };
теперь, если я хочу добавить метку времени к каждому элементу, это не работает:
allsubdirs.Select(a => a = a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
не так:
foreach (var item in allsubdirs)
item = item + "_" + DateTime.Now.ToString("hhmmss");
Я заставил его работать так:
IEnumerable<string> newallsubdirs = allsubdirs.Select(a => a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
allsubdirs = newallsubdirs;
но это как-то похоже на обман. Как правильно это сделать, пожалуйста?
5 ответов
Linq для запрос, а не обновление. Запросы Linq возвращают новая собрание основанное на проекциях, фильтрах etc. Таким образом, ваш выбор:
-
сохраните коллекцию" new " обратно в переменную (или новую переменную, если необходимо):
allsubdirs = allsubdirs.Select(a => a = a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
-
используйте интерфейс для записи, например
IList<T>
иfor
петли:IList<string> allsubdirs = new List<string>() { "a", "b", "c" }; for(int i=0; i<allsubdirs.Count(); i++) allsubdirs[i] = allsubdirs[i] + "_" + DateTime.Now.ToString("hhmmss");
главное отличие в том, что Select
не изменяет исходную коллекцию, а for
loop делает.
мое мнение:Select
чище и не "обманывает" - вы просто добавляете проекцию поверх оригинальной коллекции.
ваша первая попытка
allsubdirs.Select(a => a = a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
возвращает новый IEnumerable
но не меняет старый. Для этого используйте
allsubdirs = allsubdirs.Select(a => a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
попробуйте это:-
var result= allsubdirs.Select(x => String.Format("{0}_{1}", x,
DateTime.Now.ToString("hhmmss")));
Если вы не хотите, чтобы сохранить его в другой переменной, рассмотрите возможность использования ToList()
.
как упоминалось в существующих ответах, an IEnumerable
коллекцию нельзя изменить, пытаясь присвоить новое значение одному из ее элементов.
однако, если элементы, содержащиеся в коллекции, имеют изменяемый тип, их можно изменить. Но для вашего примера это невозможно, потому что a string
- это непреложно.
так что если вы хотите изменить существующие элементы в IEnumerable
, сам элемент должен быть типом, поддерживающим операции модификации, как в ниже приведен пример.
public class MyItem
{
private string _value;
public MyItem(string content)
{
_value = content;
}
public void Append(string other)
{
_value += other;
}
public void ReplaceWith(Func<string, string> replacer)
{
_value = replacer(_value);
}
}
тогда вы можете использовать его так:
IEnumerable<MyItem> allsubdirs = new List<MyItem>() { new MyItem("a"), new MyItem("b"), new MyItem("c") };
foreach (var item in allsubdirs)
item.Append("_" + DateTime.Now.ToString("hhmmss"));
D Stanley ответил правильно. Я хотел бы добавить к его ответу, так как название Update item in IEnumerable
подразумевается, что должен быть обновлен только один элемент.
Linq предназначен для запросов, а не для обновления.
и
используйте записываемый интерфейс, такой как IList и цикл for
для обновления одного элемента, вы можете извлеките индекс элемента для обновления и используйте этот индекс для его обновления.
например:
IList<string> allsubdirs = new List<string>() { "a", "b", "c" };
int index = allsubdirs.IndexOf("a");
allsubdirs[index] = "d";