FarseerPhysics を MonoTouch でコンパイルできるように取り組んでいます。System.Collections.Generic で HashSet を使用すると問題なく動作しますが、Farseer には Xbox 360 と Windows Phone で使用する独自の Hashset クラスがあるため、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>();
}
Farseer ハッシュセット クラス ファイルの #if に IPHONE を追加すると、2 つの問題が発生します。
1 つ目は、HashSet が System.Collections.Generic.HashSet と FarseerPhysics.Common.HashSet の間のあいまいな参照であるとコンパイラが言う宣言でエラーが発生することです。このエラーは、Visual Studios コンパイラでは発生しません。これは、Xbox 360 と Windows Phone .Net API にはない Hashset を MonoTouch が実装しているためだと思われます。どちらにもハッシュセットがない理由はよくわかりませんが、ハッシュセットの Farseers バージョンを使用するのが最善だと思います。
もう 1 つの問題は、iPhone デバイスでアプリを実行する際に FarseerPhysics.Common.Hashset (つまり、新しい FarseerPhysics.Common.HashSet();) を使用する宣言を明示的に設定すると、エラーが発生することです。
「--aot-only で実行中にメソッド 'System.Collections.Generic.Dictionary'2:.ctor()' を JIT コンパイルしようとしています。\n'
また、このエラーはシミュレーターでは発生せず、実際のデバイスでのみ発生することも指摘しておく必要があります。