我正在努力让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)构造函数提供该类型的实例。