我正在尝试为特定实例的struct方法创建委托。但是,结果是创建了一个新的struct实例,当我调用该委托时,它会在新创建的实例上执行该方法而不是原始实例。
static void Main(string[] args)
{
Point A = new Point() { x = 0 };
Action move = A.MoveRight;
move();
//A.x is still zero!
}
struct Point
{
public int x, y;
public void MoveRight()
{
x++;
}
}
实际上,在这个例子中发生的是在委托创建者上创建一个新的struct Point实例,并且在通过delagate调用时对该方法执行该方法。
如果我使用类而不是结构,问题就解决了,但我想使用结构。我也知道有一个解决方案,创建一个开放的委托,并将结构作为第一个参数传递给委托,但这个解决方案似乎相当沉重。这个问题有什么简单的解决方案吗?
答案 0 :(得分:8)
不,没有办法解决这个问题。您是否有特定的原因来使用struct
?除非您特别需要它,否则您应该使用class
。
顺便提一下,你已经创建了一个可变结构(一个可以改变其值的结构),这可以毫不夸张地说是诅咒。你需要使用一个班级。
答案 1 :(得分:6)
可变结构是邪恶的,不应该使用!*
您可以将struct
更改为不可变,并使用MovePoint
方法返回结构的新值:
struct Point {
private readonly int x, y;
public Point(x, y) {
this.x = x; this.y = y;
}
public struct MoveRight() {
x++;
}
}
然后你使用Func<Point, Point>
来表示改变这一点的操作:
Func<Point, Point> move = a => a.MoveRight;
Point A = new Point() { x = 0 };
Point newA = move(A);
// newA.x is 1, but A.x is still 0, because struct is immutable
Point anotherA = move(newA);
// move the point again...
*)当然,有些情况下它们可能有用,但如果你的情况就是其中之一,你就不会问这个问题。
答案 2 :(得分:1)
是否可能会在办公室使用C#引起剧痛。在3D引擎中,我们可以进行任何形式的魔鬼工作。因此,例如,在Unity3D引擎中,Vector3是通过函数Set(x,y,z)构造的,甚至可以更改x,y,z,因为它们是公共字段。一切都是为了提高速度(例如,如果对此计算量较少,那么您将拥有其他东西。
static void Main(string[] args)
{
Point A = new Point() { x = 0 };
MyPointDelegate<Point> move=(ref Point p)=> p.MoveRight();
move(ref A);
Console.Write(A.x);
//A.x is one!
}
public delegate void MyPointDelegate<Point>(ref Point t);
struct Point
{
public int x, y;
public void MoveRight()
{
x++;
}
}