linq 在 Xcode 上編譯錯誤?

例如

internal IOrderedEnumerable& GetOrderHeroList()
{
var list =_heroList
.OrderBy(n =&> n.Exp &< n.MaxExp ? 0 : 1) .ThenBy(n =&> n.Level)
.ThenBy(n =&> n.Phase)
.ThenBy(n =&> n.Star)
.ThenBy(n =&> n.Id);
return list;
}

提示 jit 編譯錯誤,網上除了一個 LINQ to iOS - An easy solution for using LINQ to Objects in your Unity mobile games 都沒看到解決辦法,都是說不用 linq。有簡單點的解決辦法嗎?


簡短說:如果在Unity3D/iOS用LINQ-to-Object遇到「JIT問題」的話那隻能不用LINQ了…或者用題主提到的LINQ-to-iOS

背景知識:問題是AOT編譯+泛型方法這種組合。

先列舉幾個基本事實:

  • LINQ-to-Objects的擴展方法很多都是泛型方法。題主用的例子多半就是用Enumerable上的泛型的擴展方法,例如 Enumerable.OrderBy(TSource, TKey) Method (IEnumerable(TSource), Func(TSource, TKey)) (System.Linq) 。
  • Unity3D在iOS上(目前還)依賴Mono的AOT編譯功能來實現腳本的執行。iOS不允許第三方軟體做JIT編譯,所以雖然Mono自身可以做JIT編譯,在iOS上它卻只能Full AOT編譯。
  • Unity3D使用的Mono版本一直很老,而且因為不肯跟Xamarin簽新的技術支持合約而一直沒有更新Mono版本。
  • C#的泛型的「實例化」(instantiation)通常都是在運行時做的,然後相關方法由JIT編譯器來編譯。
  • 老版本的Mono的AOT功能無法支持泛型實例化,而是把它們交給JIT編譯器處理;後來支持稍微改進了一點,但還是有些限制(可以參考Xamarin.iOS的文檔 Limitations)。請參考文檔:http://www.mono-project.com/docs/advanced/aot/#limitations 和 AOT | Mono
    • As of Mono 2.0, AOT compilation is only supported for non-generic methods. support for generics is currently under development.
    • Limitation: Generic Interface Instantiation
    • While generics are supported, there are some rare cases that are not supported.
    • The following class of interface dispatch is not supported in FullAOT mode: …

把這些事實全部結合起來,在iOS上通過Unity3D使用C#的LINQ泛型擴展方法時,就會遇到諸如這樣的錯誤信息:

ExecutionEngineException: Attempting to JIT compile method "System.Linq.Enumerable:Sum& (System.Collections.Generic.IEnumerable`1&,System.Func`3&)" while running with --aot-only.

LINQ-to-iOS之所以能工作,在官網上寫得很清楚:LINQ to iOS - An easy solution for using LINQ to Objects in your Unity mobile games

The way LINQ to iOS works

As you know most LINQ methods are generic. Generic methods that you know call the other generic methods inside their implementation. However Mono compiler has limitations to nested generics. It cannot process too much nested generic methods and classes and so you receive JIT-compile errors in runtime.

We have reimplemented all the LINQ methods, but we left only public methods generic. All the core logic is implemented inside non-generic methods, with appropriate cast in the end. That"s why LINQ to iOS is working flawlessly even on iOS.


推薦閱讀:

用遊戲引擎「實時」做影視特效會衝擊原本屬於「後期」的合成行業嗎?
想要進遊戲公司進行開發,到底需要什麼能力呢,該不該培訓呢。。。?
有投資者總結說採用 Unity 是手游公司倒閉的原因之一,如何評價這個判斷?
Chrome 不支持 NPAPI 後,以前 Unity 項目該何去何從?
Unity 3D 遊戲未來的就業前景如何?

TAG:編程 | Unity遊戲引擎 | 編譯器 | linq | Mono |