Это займет немного настройки вашего класса, но вот как это сделать. Сначала вам нужно, чтобы группа уведомила коллекцию о том, что вы собираетесь изменить имя, сделайте это, добавив событие и изменив установщик имени.
Сначала добавьте этот интерфейс и обработчик событий.
public delegate void TestForColisions(object sender, TestForColisionsArgs e);
public class TestForColisionsArgs : CancelEventArgs
{
public TestForColisionsArgs(object newValue)
{
NewValue = newValue;
}
public object NewValue { get; private set; }
}
public interface ITestForColisions
{
/// <summary>
/// Set the event to Canceled if there will be a collision.
/// </summary>
event TestForColisions TestForCollision;
}
Тогда пусть ваш класс реализует интерфейс
public class Group : ITestForColisions, IEquateable<Group>
{
public Int16 ID { get; private set; }
private string _Name;
public string Name
{
get { return _Name; }
set
{
//If RaiseNameChanging returns true there was a collision.
if (RaiseNameChanging(value))
{
throw new ArgumentException(String.Format("The name {0} is in use in the collection", value));
}
else
{
_Name = value;
}
}
}
protected virtual bool RaiseNameChanging(string name)
{
//Make a copy with the new name.
var newGroup = (Group)this.MemberwiseClone();
newGroup.Name = name;
var cancelEventArgs = new TestForColisionsArgs(newGroup);
if (TestForCollision != null)
{
TestForCollision(this, cancelEventArgs);
}
return cancelEventArgs.Cancel;
}
//(...)
}
Тогда вам понадобится пользовательская коллекция, которая прослушивает TestForCollision
события и обрабатывает соответственно. Для большинства методов вы можете просто вызвать версию родительского _BaseSet
, однако для любого из методов, которые изменяют набор, вам нужно будет либо подписаться, либо отказаться от подписки на событие. Я сделал Очистить, Добавить и Удалить для вас.
public class ColisionTestedCollection<T> : ISet<T>
where T : ITestForColisions
{
public ColisionTestedCollection(ISet<T> baseSet)
{
_BaseSet = baseSet;
_EqualityComparer = EqualityComparer<T>.Default;
}
public ColisionTestedCollection(ISet<T> baseSet, IEqualityComparer<T> equalityComparer)
{
_BaseSet = baseSet;
_EqualityComparer = equalityComparer;
}
private ISet<T> _BaseSet;
private IEqualityComparer<T> _EqualityComparer;
void TestItemsForCollision(object sender, TestForColisionsArgs e)
{
if (_BaseSet.Contains((T)e.NewValue, _EqualityComparer))
{
e.Cancel = true;
}
}
public bool Add(T item)
{
bool added = _BaseSet.Add(item);
if(added)
item.TestForCollision += TestItemsForCollision;
return added;
}
void ICollection<T>.Add(T item)
{
((ICollection<T>)_BaseSet).Add(item);
item.TestForCollision += TestItemsForCollision;
}
public bool Remove(T item)
{
bool removed = _BaseSet.Remove(item);
if (removed)
item.TestForCollision -= TestItemsForCollision;
return removed;
}
public void Clear()
{
foreach (var item in _BaseSet)
item.TestForCollision -= TestItemsForCollision;
_BaseSet.Clear();
}
public void ExceptWith(IEnumerable<T> other)
{
throw new NotImplementedException();
}
public void IntersectWith(IEnumerable<T> other)
{
throw new NotImplementedException();
}
public void SymmetricExceptWith(IEnumerable<T> other)
{
throw new NotImplementedException();
}
public void UnionWith(IEnumerable<T> other)
{
throw new NotImplementedException();
}
//The rest of the functions will just be simply calling _BaseSet's version of the method.
public bool IsProperSubsetOf(IEnumerable<T> other)
{
return _BaseSet.IsProperSubsetOf(other);
}
//(snip)
}