MonoTouch JIT 似乎不喜欢自定义哈希集类

发布于 2024-11-09 20:38:07 字数 3079 浏览 0 评论 0原文

我正在努力让 FarseerPhysics 在 MonoTouch 中编译。当我在 System.Collections.Generic 中使用 HashSet 时,它工作得很好,但是 Farseer 有自己的 Hashset 类,它用于 Xbox 360 和 Windows Phone,所以我认为也包含 IPHONE 的哈希集是有意义的。

这是 Farseer 哈希集代码:

#if WINDOWS_PHONE || XBOX || IPHONE

//TODO: FIX

using System;
using System.Collections;
using System.Collections.Generic;

namespace FarseerPhysics.Common
{

    public class HashSet<T> : ICollection<T>
    {
        private Dictionary<T, short> _dict;

        public HashSet(int capacity)
        {
            _dict = new Dictionary<T, short>(capacity);
        }

        public HashSet()
        {
            _dict = new Dictionary<T, short>();
        }

        // Methods

#region ICollection<T> Members

        public void Add(T item)
        {
            // We don't care for the value in dictionary, Keys matter.
            _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 IEnumerator<T> GetEnumerator()
        {
            return _dict.Keys.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _dict.Keys.GetEnumerator();
        }

        // Properties
        public int Count
        {
            get { return _dict.Keys.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        #endregion
    }
}
#endif

它们的使用方式如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using FarseerPhysics.Collision;
using FarseerPhysics.Common;
using FarseerPhysics.Controllers;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;

class World
{
(...)
        private HashSet<Body> _bodyAddList = new HashSet<Body>();
        private HashSet<Body> _bodyRemoveList = new HashSet<Body>();
        private HashSet<Joint> _jointAddList = new HashSet<Joint>();
        private HashSet<Joint> _jointRemoveList = new HashSet<Joint>();
}

当我将 IPHONE 添加到 Farseer 哈希集类文件中的 #if 时,存在两个问题。

第一个是我在声明中遇到错误,编译器表示 HashSet 是 System.Collections.Generic.HashSet 和 FarseerPhysics.Common.HashSet 之间的不明确引用。 Visual Studios 编译器中不会出现此错误。我怀疑这是因为 MonoTouch 确实实现了 Hashset,而 Xbox 360 和 Windows Phone .Net API 都没有。不太清楚为什么其中任何一个都没有哈希集,但我怀疑对我来说最好使用 Farseers 版本的哈希集。

另一个问题是,如果我在 iPhone 设备上运行应用程序时显式设置声明以使用 FarseerPhysics.Common.Hashset(即 new FarseerPhysics.Common.HashSet();),则会收到错误

'尝试 JIT 编译方法 'System.Collections.Generic.Dictionary'2:.ctor()' 使用 --aot-only 运行时。\n'

我还应该指出此错误不会发生在模拟器中,只会发生在实际设备上。

I'm working on getting FarseerPhysics to compile in MonoTouch. It works fine when I use the HashSet in System.Collections.Generic, however Farseer has its own Hashset class it uses for Xbox 360 and Windows Phone, so I thought it would makes sense to also include that hashset for IPHONE.

This is the Farseer hashset code:

#if WINDOWS_PHONE || XBOX || IPHONE

//TODO: FIX

using System;
using System.Collections;
using System.Collections.Generic;

namespace FarseerPhysics.Common
{

    public class HashSet<T> : ICollection<T>
    {
        private Dictionary<T, short> _dict;

        public HashSet(int capacity)
        {
            _dict = new Dictionary<T, short>(capacity);
        }

        public HashSet()
        {
            _dict = new Dictionary<T, short>();
        }

        // Methods

#region ICollection<T> Members

        public void Add(T item)
        {
            // We don't care for the value in dictionary, Keys matter.
            _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 IEnumerator<T> GetEnumerator()
        {
            return _dict.Keys.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _dict.Keys.GetEnumerator();
        }

        // Properties
        public int Count
        {
            get { return _dict.Keys.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        #endregion
    }
}
#endif

They're used as such:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using FarseerPhysics.Collision;
using FarseerPhysics.Common;
using FarseerPhysics.Controllers;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;

class World
{
(...)
        private HashSet<Body> _bodyAddList = new HashSet<Body>();
        private HashSet<Body> _bodyRemoveList = new HashSet<Body>();
        private HashSet<Joint> _jointAddList = new HashSet<Joint>();
        private HashSet<Joint> _jointRemoveList = new HashSet<Joint>();
}

There are two problems when I add IPHONE to the #if in the Farseer hashset class file.

The first is I get an error in the declarations where the compiler says HashSet is an ambigous reference between System.Collections.Generic.HashSet and FarseerPhysics.Common.HashSet. This error does not occur in Visual Studios compiler. I suspect this is because MonoTouch does implement Hashset wherein Xbox 360 and Windows Phone .Net APIs don't have either. Not too sure why there is no hashset for either of those but I suspect it would be best for me to use Farseers versio of hashset.

The other problem is that if I explicitly set the declaration to use FarseerPhysics.Common.Hashset (i.e. new FarseerPhysics.Common.HashSet();) on running the app on an iPhone device I get the error

'Attempting to JIT compile method 'System.Collections.Generic.Dictionary'2:.ctor()'
while running with --aot-only.\n'

I should also point out this error does not occur in the simulator, only on an actual device.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

赠意 2024-11-16 20:38:07

第一个问题是引用不明确,因为现在您的类正在使用两个名为 HashSet 的类,而您没有指定您想要哪个。您可以删除 using System.Collections.Generic; 行,或在文件顶部添加 using HashSet = FarseerPhysics.Common.HashSet; 语句。这将使编译器知道具体使用哪一个。

您遇到的 JIT 编译错误是 monotouch 的几个限制之一:您不能真正在字典键中使用值类型,因为 mono 编译器尝试实例化比较器对象的方式。有关详细信息,请查看此处:http://monotouch.net/Documentation/Limitations(搜索“value类型作为字典键”)。

要解决此问题,您需要在新类型中实现 IEqualityComparer 接口,并向 Dictionary(IEqualityComparer) 构造函数提供该类型的实例。

The first issue, with the ambiguous reference, is because now you have two classes called HashSet that are being used by your class, and you're not specifying which one you want. You can remove the using System.Collections.Generic; line, or add a using HashSet = FarseerPhysics.Common.HashSet; statement to the top of the file. That will make the compiler know which one specifically to use.

The JIT compilation error you're getting is one of a few limitations of monotouch: you can't really use value types in dictionary keys, because of the way the mono compiler will try to instantiate a comparer object. For more info, look here: http://monotouch.net/Documentation/Limitations (search for "value types as dictionary keys").

To work around this issue, you need to implement the IEqualityComparer interface in a new type and provide an instance of that type to the Dictionary(IEqualityComparer) constructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文