ConvertAll
Just to be explicit, here is how you use ConvertAll.
In the case where class B has a member of class A called m_a, do this:
B[] arrB;
A[] arrA = Array.ConvertAll(arrB, b => b.m_a);
.
If class B has some member data that you need to manipulate before you can return an object of type A (such as turning a bunch of numerical values into a string description), do this:
class B
{
public static A makeAfromB(B b)
{
// Do something with B data...
A a = new A("data made from B data")
return a;
}
// rest of class B implementation ...
}
// somewhere else in your code...
A[] arrA = Array.ConvertAll(arrB, new Converter<B, A>(B.makeAfromB));
.
You can also use Lambda functions:
A[] arrA = Array.ConvertAll(arrB, new Converter<B, A>(
delegate(B b)
{
// Do something with B data, though object b is const
A a = new A("data made from B data")
return a;
}));
.
It would be nice if ConvertAll could use the implicit operator to do the conversion, but I haven't figured out how to do that.
.
Cast
@Randolpho @bottlenecked
For the cases where you simply want to iterate and would prefer not to make a copy, using cast makes sense. However I have been unable to make it work.
I have an InkPoint class which has a Point object and some other members. I want to call the DrawLines(Pen, Point[]) function. However, I have an array of InkPoint[].
Here is my class and the code I currently have to use, which makes a copy:
public class InkPoint
{
public InkPoint(int x, int y)
{
point = new Point(x, y);
}
public Point point { get; set; }
public static implicit operator Point(InkPoint p)
{
return p.point;
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
InkPoint[] inkPoints = { new InkPoint(1,2), new InkPoint(3,4) };
Point[] points = Array.ConvertAll(inkPoints, x => x.point);
Pen pen = new Pen(Color.Black, 1);
e.Graphics.DrawLines(pen, points);
}
.
I would rather call this, but it won't compile, citing invalid arguments:
e.Graphics.DrawLines(pen, inkPoints.Cast<Point>()); // Compile err: invalid args
.
I've also tried iterating over a cast, but it throws an exception, citing the cast is not valid
foreach (Point p in inkPoints.Cast<Point>()) { } // Exception: cast not valid
.
I don't understand why the specified cast is not valid since I've defined an implicit operator. I'm able to do the following just fine:
InkPoint ip = new InkPoint(10, 20);
Point p1 = ip; // implicit conversion
Point p2 = (Point)ip; // cast
.
For me, the situation is actually slightly more complicated than that. I actually have a list of InkPoints, List<InkPoint>, but the DrawLines function accepts only arrays. So my code looks like this:
List<InkPoint> inkPoints = new List<InkPoint>();
inkPoints.Add(new InkPoint(5, 10));
inkPoints.Add(new InkPoint(10, 15));
Point[] points = inkPoints.ConvertAll<Point>(x => x.point).ToArray();
I can rearrange it slightly to this:
Point[] points = Array.ConvertAll(inkPoints.ToArray(), x => x.point);
.
So I think there's actually two copies happening here. This is annoying since all I want to do is draw the lines. It doesn't seem unreasonable that the DrawLines function should be able to iterate over some array/list that contains references to objects that can be implicitly converted to Point objects.