MonoTouch JIT似乎不喜欢自定义hashset类

时间:2011-05-26 12:17:54

标签: c# iphone xamarin.ios hashset farseer

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

这是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 Studios编译器中不会发生此错误。我怀疑这是因为MonoTouch确实实现了Hashset,其中Xbox 360和Windows Phone .Net API都没有。不太确定为什么没有任何一个的hashset,但我怀疑我最好使用hashset的Farseers versio。

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

  

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

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

1 个答案:

答案 0 :(得分:2)

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

您获得的JIT编译错误是monotouch的一些限制之一:您无法在字典键中使用值类型,因为单声道编译器将尝试实例化比较器对象。有关详细信息,请查看此处:http://monotouch.net/Documentation/Limitations(搜索“值类型作为字典键”)。

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