How to test _set.Contains(obj), when _set is HashSet<T1>, obj isT2, and T1, T2 both implement same interface?

不问归期 提交于 2019-12-24 08:49:24

问题


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 DeviceClasss (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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!