【问题标题】:How to test _set.Contains(obj), when _set is HashSet<T1>, obj isT2, and T1, T2 both implement same interface?如何测试_set.Contains(obj),当_set是HashSet<T1>,obj是T2,T1,T2都实现同一个接口?
【发布时间】:2014-04-08 19:02:01
【问题描述】:

我必须实现一个ObservableHashSet&lt;T&gt;,它可以快速(O(1))测试对象是否存在:

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); }
}

现在说我们有两种类型,都实现相同的接口:

IDevice
  ├── ActualDevice
  └── DeviceClass

界面是:

public interface IDevice {
    string Vendor { get; set; }
    string Name { get; set; }
}

我需要一种方法来快速 (O(1)) 测试 ActualDevice 是否存在于 DeviceClasss (HashSet&lt;DeviceClass&gt;) 的列表中。那么如何更改上面的ObservableHashSet&lt;T&gt;.QuickContains(T obj) 函数以允许它呢?所以我可以做这样的事情:

var classesList = new ObservableHashSet<DeviceClass>(someDataSource);
ActualDevice actualDevice = GetTheDevice();
MessageBox.Show(classesList.QuickContains(actualDevice) ? "Exists!" : "Missing...");

【问题讨论】:

  • 如果ActualDevice 等于DeviceClass,这听起来很奇怪...
  • public class ObservableHashSet&lt;T&gt; : ObservableCollection&lt;T&gt; 已经错了。哈希集不是IList。
  • @Jon,当然不是,但我需要一个可以快速测试的可观察集合(O(1)),即HashSet。你会如何解决它?
  • 为什么需要测试为O(1)?您的收藏中有多少件物品?
  • @Tal:可能是通过聚合一个HashSet 并在其上直接实现ISet&lt;T&gt; 和INotifyCollectionChanged。

标签: c# polymorphism c#-5.0


【解决方案1】:

我会将HashSet&lt;T&gt; 的项目类型设为仅包含您基于相等性测试的数据的类。目前,您正在尝试将 DeviceClass 与 ActualDevice 进行比较,这看起来很奇怪。

我的理解是您想测试ActualDevice 是否与许多DeviceClass'es 之一相关联。你可以这样做:

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
}

现在您将成员添加到集合中,如下所示:

HashSet<DeviceClassKey> items = ...;
DeviceClass dc = ...;
items.Add(DeviceClassKey.FromDeviceClass(dc));

然后你像这样测试成员资格:

HashSet<DeviceClassKey> items = ...;
ActualDevice ad = ...;
var isMember = items.Contains(DeviceClassKey.ActualDevice(ad));

我可能遗漏了您的一些要求,但这种技术可能可以扩展以涵盖它。

【讨论】:

  • 如果需要检索ActualDevice,可以使用Dictionary&lt;DeviceClassKey, ActualDevice&gt;。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 2010-12-18
  • 2018-10-25
相关资源
最近更新 更多