Rhino 8 C# IEnumerable instead of List?

Previously when you changed the C# Component input to type List Access, the data would come into the component as a List now it comes in as an IEnumberable.

This seems fairly unusable unless you are using System.Linq; and then convert it into an array .ToArray(); Am I missing something?

Use .ToList() or .ToArray() methods to convert the IEnumerable to a List or an array, respectively.

@farouk.serragedine That doesn’t work unless you I use using System.Linq (See above and image below). However, the real question is:

Should users really need to have a knowledge of Linq before they can do basic things with the C# Script component? (you can guess my answer).

No need for Linq.

You can create a list of desired type (List) and copy the content to the list. Like so:

//Rolf

2 Likes

I think using System.Linq should be always included as default, I’m still annoyed that they took it down, and it was a long time ago. Or return to List<> instead of IEnumerable<>, it doesn’t make sense this middle ground.

As Ril says but in one line:

var points = new List<Point3d>(){ P };
a = points;

or

var points = new Point3d[] { P };
a = points;
1 Like

@eirannejad was there are reason we switched to IEnumerable?

@stevebaer I made the change to make it clear the input list is immutable. We can always convert the enumerable into a list in the script. The same IEnumerable is also passed to python scripts.

I can change that back if this is an issue

It has the potential to make scripts less efficient as I can see scripters immediately making copies of the input to be able to work with List syntax. All of the workarounds described above involve creating a new list as a copy of the input IEnumerable. It is also “different” and can cause confusion with people trying to get their older scripts working in the new component.

1 Like

RH-78321 Pass Grasshopper list inputs as List<> into the scripts. Figure out a way to generate python 3 lists for inputs

RH-76311 Allow indexing and slicing on grasshopper inputs lists in python 3

1 Like
  private void RunScript(IEnumerable<Point3d> pts, out object a)
  {
    // pts.GetType()
    // System.Collections.Generic.List`1[Rhino.Geometry.Point3d]
    List<Point3d> ptList = pts as List<Point3d>;
    a = null;
    if (ptList == null) return;
    // do some list stuff
    ptList.Add(new Point3d(0,0,0));
    ptList.Add(new Point3d(10,10,123));
    PolylineCurve plCrv = new PolylineCurve(ptList);
    a = plCrv;
  }

As the Type that implements IEnumerable is a List,
what about casting to
List<pts> (or whatever type you set in the Type-Hint for the variable?

my guess - this is faster then rewriting a new list - and a nice Workaround (?)
but I also might have overseen something - kind regards -tom

I think we should just pass in a List if the first thing you try to do is cast and start testing for success. There are many other collection types that implement IEnumerable.

If you want us to have an immutable list, why not just give us an ImmutableList?

Edit: introduced in 5 I guess, so not available in 4.8. Ok… seems like it would still be possible to implement what you want to give us as a Rhino class.

Grasshopper’s lower level data access routines provide a List. It may not make sense to modify the list, but it already is a list

Hopefully that doesn’t provide the opportunity for obscure bugs if a given output goes to a few different receivers and the first data receiver in line decides to edit the list.

It has been this way for over 10 years. Outputs are not affected by tweaks to the input list.

1 Like

Well, you guys know what you’re doing!

I just didn’t see how that could be without making (unnecessary, if the receiver isn’t supposed to edit it but has the capability to do so) copies of the list to pass to each receiver.

Dear @eirannejad
Seams like IList was choosen.
The Autocomplete in the c# editor in Grasshopper suggests an extension-Method “ToArray()”.
Where is this extension implemented ?
What I am missing - a using statement ?

  private void RunScript(IList<double> x, ref object a)
  {
    // creates an error - what is missing ?
    double[] xAsArray = x.ToArray();
    
    a = null;
  }

my current (bulky ?) workaround is a generic function - any improvements are welcome…

private static T[] IListToArray<T>(IList<T> ilist)
  {
    T[] back = new T[ilist.Count];
    ilist.CopyTo(back,0);
    return back;
  }

ToArray() is part of System.Linq extensions for an IList

We chose IList since you can index that like an array

1 Like

thanks for the info.
maybe a default using statement for System.Linq ?

Great. I added a YT to take care of this

RH-81237 Add System.Linq as a default import to csharp templates

2 Likes