NetFabric/NetFabric.Hyperlinq

Select then ToList() doesn't work ?

LoisBoombyte opened this issue · 2 comments

Hi, I executed this simple test in Unity and the ToList() doesn't work well... ?!

public List<InboxItem> _firstList = null;

 public class InboxItem
 {
     public int int1;
     public float float1;
     public int int2;
 }

 //I just initialize the list with 10.000 items
 private void Start()
 {
     _firstList = new List<InboxItem>(100000);
     for (int i = 0; i < 100000; i++)
     {
         _firstList.Add(new InboxItem()
         {
             int1 = i,
             float1 = i,
             int2 = 2 * i
         });
     }
 }

private void TestSelectThenToListHyperLinq()
 {
     Debug.Log("TestSelectThenToListHyperLinq");
     var select = _firstList.AsValueEnumerable().Select(x => x.int1);
     var list = select.ToList();
     var array = select.ToArray();
     Debug.Log("list count = " + list.Count);  //return 0 !!!!
     Debug.Log("array Length = " + array.Length); //return n
 }

 private void TestSelectThenToListLinq()
 {
     Debug.Log("TestSelectThenToListLinq");
     var select = _firstList.Select(x => x.int1);
     var list = select.ToList();
     var array = select.ToArray();
     Debug.Log("list count = " + list.Count); //return n
     Debug.Log("array Length = " + array.Length); //return n
 }

if I use Linq's ToList() after your Select() it also work correctly. Problems seems to be when I use your own ToList()

R-033 commented

Had the same issue. This is caused by unsafe cast from List to ListLayout not working the same way in .Net Framework/Mono. The problem was in ListExtensions class. I did quite a bit of testing and ended up rewriting the problematic bit completely. I don't know if this is the best solution but it worked for me.

static List<TSource> WrapArray(TSource[] source)
{
  var result = new List<TSource>();
  ref var layout = ref ILExtensions.AsRef<ListLayout<TSource>>(ILExtensions.AddressOf(result));
  layout.Items = source;
  layout.Count = source.Length;
  return result;
  }
  
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MonoObject
{
  public IntPtr MonoVTable;
  public IntPtr Monitor;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ListLayout<T>
{
  public MonoObject Mono;
  public T[] Items;
  public int Count;
  public int Version;
}

Easier solution is to just use older version of this repo (around beginning of 2020) before they dropped .Net Framework support.