ConvertAll
Просто для ясности, вот как вы используете ConvertAll.
В случае, если class B
имеет член class A
с именем m_a
, сделайте следующее:
B[] arrB;
A[] arrA = Array.ConvertAll(arrB, b => b.m_a);
.
Если class B
имеет некоторые данные-члены, которыми вам нужно манипулировать, прежде чем вы сможете вернуть объект типа A (например, преобразование набора числовых значений в описание строки), выполните следующее:
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));
.
Вы также можете использовать лямбда-функции:
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;
}));
.
Было бы неплохо, если бы ConvertAll мог использовать неявный оператор для преобразования, но я не понял, как это сделать.
.
Cast
@ Randolpho @ узкое место
Для случаев, когда вы просто хотите выполнить итерацию и предпочитаете не делать копию, использование преобразования имеет смысл. Однако я не смог заставить его работать.
У меня есть класс InkPoint
, в котором есть объект Point
и некоторые другие члены. Я хочу вызвать функцию DrawLines(Pen, Point[])
. Тем не менее, у меня есть массив InkPoint[]
.
Вот мой класс и код, который я сейчас должен использовать, что делает копию:
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);
}
.
Я бы скорее назвал это, но он не скомпилируется, ссылаясь на недопустимые аргументы:
e.Graphics.DrawLines(pen, inkPoints.Cast<Point>()); // Compile err: invalid args
.
Я также пытался выполнить итерации по приведениям, но выдает исключение, ссылаясь на то, что приведение не допустимо
foreach (Point p in inkPoints.Cast<Point>()) { } // Exception: cast not valid
.
Я не понимаю, почему specified cast is not valid
, поскольку я определил неявный оператор. Я могу сделать следующее очень хорошо:
InkPoint ip = new InkPoint(10, 20);
Point p1 = ip; // implicit conversion
Point p2 = (Point)ip; // cast
.
Для меня ситуация на самом деле немного сложнее. У меня на самом деле есть список InkPoints, List<InkPoint>
, но функция DrawLines
принимает только массивы. Итак, мой код выглядит так:
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();
Я могу немного изменить это так:
Point[] points = Array.ConvertAll(inkPoints.ToArray(), x => x.point);
.
Так что я думаю, что на самом деле здесь происходит две копии. Это раздражает, так как все, что я хочу сделать, это нарисовать линии. Не кажется необоснованным, что функция DrawLines
должна иметь возможность перебирать некоторый массив / список, содержащий ссылки на объекты, которые могут быть неявно преобразованы в Point
объекты.