我想做的事情看起来很简单-我想在ICollection<T>
中找到一个满足给定谓词的元素,然后用另一个替换。在C ++中,我会这样写:
for(auto &element : collection) {
if(predicate(elem)) {
element = newElement;
}
}
通过引用获取元素并重新分配。但是在做
foreach(ref var element in collection)
C#中的无法编译,而且我不确定如果编译后它甚至可以执行我想要的操作。如何访问集合中的物理参考进行修改?
我的方法签名是否有帮助:
public static void ReplaceReference<T>(
ICollection<T> collection,
T newReference,
Func<T, bool> predicate)
编辑:
由于不清楚,我不能只拿ICollection<T>
并将其更改为其他名称。我得到一个ICollection
-这就是我所知道的,我无法更改。无论我多么希望自己成为IList
,还是IEasilyReplacable
我都无法影响它。
答案 0 :(得分:2)
ICollection<T>
在这种情况下不是最好的。 IList<T>
允许您分配索引器。ICollection<Wrapper<T>> collection = ...;
foreach(var wrapper in collection)
{
wrapper.Value = newValue;
}
答案 1 :(得分:1)
据我了解,您想根据给定的谓词替换集合中的特定项目,我尝试了以下代码,对我来说很好用。
我创建了一个包含4个项目的字符串列表,我让我的通用方法搜索值为“名称1”的字符串是否正确,应该将其更改为值“名称5”。
我已经使用控制台应用程序对其进行了测试,因此您可以通过使用Console.WriteLine();创建显示列表值的forloop来对其进行测试。
public void Main(string[] args)
{
List<string> list = new List<string>();
list.Add("Name 1");
list.Add("Name 2");
list.Add("Name 3");
list.Add("Name 4");
Func<string, bool> logicFunc = (listItemValue) => listItemValue == "Name 1";
ReplaceReference(list, "Name 5", logicFunc);
}
public static void ReplaceReference<T>(ICollection<T> collection, T newReference, Func<T, bool> predicate)
{
var typeName = typeof(T).Name;
var newCollection = collection.ToList();
for (int i = 0; i < newCollection.Count; i++)
{
if (predicate(newCollection[i]))
{
newCollection[i] = newReference;
}
}
}
答案 2 :(得分:-1)
所以我把头撞在墙上,想出了一个非常简单的解决方案来解决特定的替换问题,即找到,删除然后添加。
var existing = collection.FirstOrDefault(predicate);
if (existing != null)
{
collection.Remove(existing);
collection.Add(newReference);
}
但是,我认为这是解决我的foreach
问题的一种变通方法,因此已将此问题发布为后续问题:Grab element from a Collection by reference in a foreach
编辑:
对于丹尼尔·A·怀特的评论:
仅处理第一个是我打算做的,但是可以轻松地将其更改为全部替换:
var existing = collection.Where(predicate);
foreach(var element in existing)
{
collection.Remove(element);
}
for(int i = 0; i < existing.Count); ++i)
{
collection.Add(newReference);
}
关于排序-ICollection
不一定要排序。因此,解决该问题的方法将是创建一个通用性较低的新方法
static void ReplaceReference<T>(
IList<T> list,
T newReference,
Func<T, bool> predicate)
将使用索引器替换值
for(int i = 0; i < list.Count; ++i)
{
if(predicate(list[i]))
{
list[i] = newReference;
// break here if replace-one variant.
}
}
现在,在main方法中,我们检查集合是否为IList,因此是有序的,并将其传递给有序的版本:
if(collection is IList<T> list)
{
ReplaceReference(list, newReference, predicate);
return;
}
================================================ ==========================
旁注:当然也有dumbo方法:
var newCollection = new List<T>();
foreach(var element in collection)
{
newList.Add(predicate(element) ? newReference : element);
}
collection.Clear();
foreach(var newElement in newCollection)
{
collection.Add(newElement);
}
但是效率很低。