对于这种情况,我有两种解决方案。
第一个解决方案
我们可以创建一个ExcepWith
方法,允许我们删除 aICollection<T>
中已经存在的所有项目 give a IEnumerable<T>
。这种方法的代码如下:
public static int ExceptWith<TItem>
(
this ICollection<TItem> collection,
IEnumerable<TItem> other
)
{
if (ReferenceEquals(collection, null))
{
throw new ArgumentNullException("collection");
}
else if (ReferenceEquals(other, null))
{
throw new ArgumentNullException("other");
}
else
{
int count = 0;
foreach (var item in other)
{
while (collection.Remove(item))
{
count++;
}
}
return count;
}
}
现在您有了string[]
用户的输入,该数组是 anIEnumerable<string>
但不是 an ICollection<string>
...,很容易解决如下:
而不是这个:
string[] AttributeTags =
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
);
你来做这件事:
var AttributeTags =
new List<string>
(
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
)
);
甚至这样:
var AttributeTags =
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
).ToList();
现在你可以这样做:
AttriuteTags.ExceptWith(existingTags);
由于attribute.AttributeTag的类型不是IEnumerable<string>
你使用Select:
AttriuteTags.ExceptWith(attribute.AttributeTag.Select(item => item.value));
这样就只剩下列表中的新标签了。
注意:这个方法依赖于 Remove 的实现,如果你需要做一个特殊的比较,那么你不走运这个方法。
第二种解决方案
还有另一种方法。您可以使用类中的“除外” Enumerable
。
string[] AttributeTags =
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
);
var newTags = AttributeTags.Except(existingTags);
由于attribute.AttributeTag的类型不是IEnumerable<string>
你使用Select:
string[] AttributeTags =
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
);
var newTags = AttributeTags.Except
(
attribute.AttributeTag.Select(item => item.value)
);
这放入了新标签,好吧,新标签。
注意:如果你需要做一个特殊的比较,那么你应该使用方法的其他重载:
string[] AttributeTags =
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
);
var newTags = AttributeTags.Except(attribute.AttributeTag, equalityComparer);
遗憾的是,equalComparer 是实现 IEqualityComparer 的类的对象,这意味着您不能在其中使用 lambda。为此,您可以添加此类:
public class CustomEqualityComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> _comparison;
private Func<T, int> _getHashCode;
public CustomEqualityComparer
(
Func<T, T, bool> comparison,
Func<T, int> getHashCode
)
{
if (ReferenceEquals(comparison, null))
{
throw new ArgumentNullException("comparison");
}
else if (ReferenceEquals(getHashCode, null))
{
throw new ArgumentNullException("getHashCode");
}
else
{
_comparison = comparison;
_getHashCode = getHashCode;
}
}
public bool Equals(T x, T y)
{
return _comparison.Invoke(x, y);
}
public int GetHashCode(T obj)
{
return _getHashCode.Invoke(obj);
}
}
现在像这样调用(例如):
string[] AttributeTags =
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
);
var newTags = AttributeTags.Except
(
existingTags,
new CustomEqualityComparer<string>
(
(a, b) => 1, //your custom comparison here
str => str.GetHashCode()
)
);
由于attribute.AttributeTag的类型不是IEnumerable<string>
你使用Select:
string[] AttributeTags =
txtAttributeTags.Text.Split
(
new string[] { "," },
StringSplitOptions.RemoveEmptyEntries
);
var newTags = AttributeTags.Except
(
attribute.AttributeTag.Select(item => item.value),
new CustomEqualityComparer<string>
(
(a, b) => 1, //your custom comparison here
str => str.GetHashCode()
)
);
添加新标签
现在您有了新标签,假设在 中newTags
,您可以对其进行迭代以添加新标签:
var now = DateTime.Now;
foreach (var item in newTags)
{
AttributeTag tag = new AttributeTag { value = item, timestamp = now };
attribute.AttributeTags.Add(tag);
}
比较解决方案
这些方法有什么区别?
- 第一个需要更少的内存
- 第一个需要定义一个新方法。
- 第一个不允许自定义
IEqualityComparer<T>
- 第二个允许延迟执行。
- 第二个使用(不需要)辅助类。