问题
I must implement an ObservableHashSet<T>
that can quickly (O(1)
) test for object existence:
public class ObservableHashSet<T> : ObservableCollection<T>{
readonly ISet<T> _set = new HashSet<T>();
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e){
base.OnCollectionChanged(e);
if (e.Action == NotifyCollectionChangedAction.Move) return;
if (e.OldItems != null)
foreach (var old in e.OldItems.Cast<T>())
_set.Remove(old.GetHashable());
if (e.NewItems == null) return;
foreach (var nu in e.NewItems.Cast<T>()) _set.Add(nu.GetHashable());
}
public bool QuickContains(T obj){ return _set.Contains(obj); }
}
Now say we have two types, both implement same interface:
IDevice
├── ActualDevice
└── DeviceClass
and the interface is:
public interface IDevice {
string Vendor { get; set; }
string Name { get; set; }
}
I need a way to quickly (O(1)
) test for certain ActualDevice
existence in a list of DeviceClass
s (HashSet<DeviceClass>
). So how can I change the ObservableHashSet<T>.QuickContains(T obj)
function above to allow it? so I'd be able to do something like this:
var classesList = new ObservableHashSet<DeviceClass>(someDataSource);
ActualDevice actualDevice = GetTheDevice();
MessageBox.Show(classesList.QuickContains(actualDevice) ? "Exists!" : "Missing...");
回答1:
I'd make the item type of the HashSet<T>
a class that only contains the data that you base the equality test on. At the moment you are trying to make a DeviceClass
compare equal to an ActualDevice
which seems odd.
My understanding is that you want to test whether an ActualDevice
is associated with one of many DeviceClass
'es. You could do it like this:
class DeviceClassKey : IEquatable<DeviceClassKey> {
//Data members here
int DeviceClassID; /* just an example */
public static DeviceClassKey FromDeviceClass(DeviceClass dc) { return ...; }
public static DeviceClassKey FromActualDevice(ActualDevice ad) { return ...; }
//add equality members here
}
And now you add members to the set like this:
HashSet<DeviceClassKey> items = ...;
DeviceClass dc = ...;
items.Add(DeviceClassKey.FromDeviceClass(dc));
And you test membership like this:
HashSet<DeviceClassKey> items = ...;
ActualDevice ad = ...;
var isMember = items.Contains(DeviceClassKey.ActualDevice(ad));
I might have missed some requirement of yours but this technique can probably be extended to cover it.
来源:https://stackoverflow.com/questions/22934328/how-to-test-set-containsobj-when-set-is-hashsett1-obj-ist2-and-t1-t2-b