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



我正在努力让FarseerPhysics在MonoTouch中编译。当我在System.Collections.Generic中使用哈希集时,它工作得很好,但Farseer有自己的哈希集类,它用于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 hashset类文件中的#if时,会出现两个问题。

首先,我在声明中得到一个错误,编译器说HashSet是System.Collections.Generic.HashSet和FarseerPhysics.Common.HashSet之间的模糊引用。这个错误在Visual Studio编译器中不会发生。我怀疑这是因为MonoTouch确实实现了Hashset,而Xbox360和WindowsPhone.NetAPI都没有。不太确定为什么这两种都没有哈希集,但我怀疑最好使用哈希集的Farseers版本。

另一个问题是,如果我明确地将声明设置为使用FarseerPhysics.Common.Hashset(即新的FarseerPhysics.Common.Hashset();)在iPhone设备上运行应用程序时,我得到错误

"正在尝试JIT编译方法"System.Collections.Generic.Dictionary"2:.ctor()"同时仅使用--aot运行。\n’

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

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

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

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

最新更新