C#中的隐式数组转换
我有以下类定义了隐式转换运算符:
class A { ... } class B { private A m_a; public B(A a) { this.m_a = a; } public static implicit operator B(A a) { return new B(a); } }
现在,我可以隐含地将A转换为B.
但为什么我不能隐含地将A []强制转换为B []?
static void Main(string[] args) { // compiles A a = new A(); B b = a; // doesn't compile A[] arrA = new A[] {new A(), new A()}; B[] arrB = arrA; }
谢谢,Malki。
正如Mehrdad Afshari所提到的那样,你在运气方面做得不好。 你必须明确,它将涉及一个数组副本。 值得庆幸的是,您可以使用单行代码来实现:
arrB = arrA.Cast().ToArray();
虽然如果你只想在foreach
语句中迭代arrB
,你可以通过省略ToArray()
来避免复制
数组协方差仅适用于引用类型和inheritance层次结构(请注意,它不是表示更改转换:只是一组具有相同大小的指针解释不同。)它不适用于值类型和用户定义的转换。
ConvertAll
只是为了明确,这是你如何使用ConvertAll。
在class B
具有名为m_a
class 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.makeAfromB));
。
您还可以使用Lambda函数:
A[] arrA = Array.ConvertAll(arrB, new Converter( 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可以使用隐式运算符进行转换会很好,但我还没弄明白如何做到这一点。
。
投
@Randolpho @bottlenecked
对于您只想迭代并且不想复制的情况,使用强制转换是有意义的。 但是我一直无法使它发挥作用。
我有一个InkPoint
类,它有一个Point
对象和一些其他成员。 我想调用DrawLines(Pen, Point[])
函数。 但是,我有一个InkPoint[]
数组。
这是我的class级和我目前必须使用的代码,它会复制:
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()); // Compile err: invalid args
。
我也试过迭代一个演员,但它抛出exception,引用演员无效
foreach (Point p in inkPoints.Cast()) { } // 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
, List
,但DrawLines
函数只接受数组。 所以我的代码看起来像这样:
List inkPoints = new List (); inkPoints.Add(new InkPoint(5, 10)); inkPoints.Add(new InkPoint(10, 15)); Point[] points = inkPoints.ConvertAll(x => x.point).ToArray();
我可以稍微重新安排它:
Point[] points = Array.ConvertAll(inkPoints.ToArray(), x => x.point);
。
所以我认为这里实际上有两个副本。 这很烦人,因为我想做的就是绘制线条。 DrawLines
函数应该能够迭代一些包含对可以隐式转换为Point
对象的对象的引用的数组/列表,这似乎是不合理的。
想象一下,如果Arrays使用与.Net中其他集合相同的语法,那么您要比较的是带有Array
的Array
。 您不会将List
与List
。 嗯,这基本上就是你想要的。
我建议使用一个简单的扩展方法来获得你想要的结果,你需要稍微改变你的语法来说’B [] arrB = arrA.ToBArray();`
static class ArrayCast { public static B[] ToBArray(this A[] source) { var result = new B[source.Length]; for (int i = 0;i < source.Length;i++) result[i] = source[i]; return result; } }