【问题标题】:C# HashSet2 to work exactly like the standard C# HashSet, not compilingC# HashSet2 与标准 C# HashSet 完全一样工作,而不是编译
【发布时间】:2012-04-20 12:49:32
【问题描述】:

我正在创建自己的 HashSet,它使用字典作为标准 HashSet。我这样做是因为 XNA XBox 的 C# 不支持 HashSet。

此代码基于我找到的示例中的代码。我已经编辑了示例以解决一些问题,但它仍然无法编译。

public class HashSet2<T> : ICollection<T>
{
    private Dictionary<T, Int16> dict;

    // code has been edited out of this example
    // see further on in the question for the full class

    public IEnumerator<T> GetEnumerator()
    {
        throw new NotImplementedException();
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return dict.GetEnumerator();
    }
}

.

'HashSet2<T>' does not implement interface member
'System.Collections.IEnumerable.GetEnumerator()'.
'HashSet2<T>.GetEnumerator()' cannot implement
'System.Collections.IEnumerable.GetEnumerator()'
because it does not have the matching return type of
'System.Collections.IEnumerator'

如果它的行为或以可能出乎意料的方式实现的内容出现偏差,我也将非常感谢有关将其修复为更像标准 HashSet 的信息。

续:stackoverflow.com/questions/9966336/c-sharp-xna-xbox-hashset-and-tuple

该类的最新版本:

public class HashSet2<T> : ICollection<T>
{
    private Dictionary<T, Int16> dict;
    // Dictionary<T, bool>

    public HashSet2()
    {
        dict = new Dictionary<T, short>();
    }

    public HashSet2(HashSet2<T> from)
    {
        dict = new Dictionary<T, short>();
        foreach (T n in from)
            dict.Add(n, 0);
    }

    public void Add(T item)
    {
        // The key of the dictionary is used but not the value.
        dict.Add(item, 0);
    }

    public void Clear()
    {
        dict.Clear();
    }

    public bool Contains(T item)
    {
        return dict.ContainsKey(item);
    }

    public void CopyTo(
        T[] array,
        int arrayIndex)
    {
        throw new NotImplementedException();
    }

    public bool Remove(T item)
    {
        return dict.Remove(item);
    }

    public System.Collections.IEnumerator GetEnumerator()
    {
        return ((System.Collections.IEnumerable)
            dict.Keys).GetEnumerator();
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return ((IEnumerable<T>)
            dict.Keys).GetEnumerator();
    }

    public int Count
    {
        get {return dict.Keys.Count;}
    }

    public bool IsReadOnly
    {
        get {return false;}
    }
}

【问题讨论】:

  • 您可以提取 .NET 的参考源代码并使用它来帮助您完成项目。
  • 有人告诉我,我在 SO 不能这样做。显然这与闭源有关。
  • @alan2here:您可以很好地查看 .NET 源代码。获取ILSpyReflector 或其他反汇编程序,打开 System.Core.dll 并浏览到 System.Collections.Generic.HashSet
  • @MichaelJ.Gray 对我来说听起来不合法。但他可以使用 Mono 的 hashset,它在 MIT X11 下发布:github.com/mono/mono/blob/master/mcs/class/System.Core/…
  • 我不想把它告诉大家,但是微软很久以前就发布了 .NET 框架的源代码......可以在 referencesource.microsoft.com/netframework.aspx 找到它,我都使用它我对 .NET 世界中的工作原理感到好奇的时候。

标签: c# collections xna hashset xbox


【解决方案1】:

您想枚举键,而不是字典。试试这个:

public IEnumerator GetEnumerator()
{
    return ((IEnumerable)dict.Keys).GetEnumerator();
}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    return ((IEnumerable<T>)dict.Keys).GetEnumerator();
}

【讨论】:

  • 我得到“'HashSet2' 没有实现接口成员'System.Collections.IEnumerable.GetEnumerator()'。'HashSet2.GetEnumerator()' 不能实现'System.Collections .IEnumerable.GetEnumerator()' 因为它没有匹配的返回类型 'System.Collections.IEnumerator'。"
  • IEnumerator 和 IEnumerable 在“public IEnumerator GetEnumerator()”和“return ((IEnumerable)dict.Keys).GetEnumerator();”中分别给出“使用泛型类型 'System.Collections.Generic.IEnumerator' 需要 1 个类型参数”。该类也仍然报错。
  • 试试using System.Collections;
【解决方案2】:

关键是HashSet的GetEnumerator返回枚举类型T的枚举器,而字典的GetEnumerator返回枚举KeyValue对象的枚举器。

更新

改成下面这样:

public IEnumerator GetEnumerator()
{
    dict.Keys.GetEnumerator();
}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    return dict.Keys.GetEnumerator();
}

【讨论】:

  • IEnumerator in "public IEnumerator GetEnumerator()" 给出错误“使用泛型类型 'System.Collections.Generic.IEnumerator' 需要 1 个类型参数。”
【解决方案3】:

您可以简单地使用 Mono 的 HashSet&lt;T&gt;。您可能需要对 #if 进行一些小改动,或者删除一些接口/属性,但它适用于 .net。

它使用的是 MIT X11 许可证,这是允许的。 https://github.com/mono/mono/blob/master/mcs/class/System.Core/System.Collections.Generic/HashSet.cs

【讨论】:

  • 这是可能的,尽管我不能花大量时间尝试去那里安装库并与我的程序集成,编辑它以修复它,因为它已经过时或用于错误的环境或使用 #if 或其他本身会破坏更多东西的东西,一两天后,当它全部安装和东西时,这里还有几个关于如何做的问题,然后我最终放弃并且仍然没有解决方案。感谢您的回答,我会研究它,但在我研究了其他可能性之后。
  • 在两分钟内使文件在正常的 .net 4 中编译。它不需要单声道的任何其他部分。我不得不删除 DebuggerTypeProxy 属性,但这是一个小改动。
  • 酷,谢谢。还有与标准 HashSet 的相似之处,如果不是,我可以理解它的代码,以便我可以更改它。仍然感觉像是一罐潜在的递归蠕虫。我认为 Aliostad 的答案可能有一个更简单的解决方案,但并不完全存在。如果没有,我稍后会在这里回复。
【解决方案4】:

刚刚查看了源代码,Dictionary&lt;TKey, TValue&gt; 中 GetEnumerator 的所有实现都返回 KeyCollection.Enumerator/ValueCollection.Enumerator 对象而不是 IEnumerator&lt;T&gt;(这是我们需要的)。好消息是Key/ValueCollation.Enumerator 实现了System.Collection.IEnumeratorIEnumerator&lt;T&gt; 接口,因此您可以安全地转换为这些类型。

尝试这样做:

public IEnumerator GetEnumerator()
{
    return (IEnumerator)dict.Keys.GetEnumerator();
}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    return (IEnumerator<T>)dict.Keys.GetEnumerator();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-07
    • 2021-05-23
    • 2013-07-14
    • 2012-07-18
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多