简体   繁体   English

C#XNA在构造函数中通过引用类传递

[英]C# XNA pass by reference classes in constructor

I'm making a vector graphics game in XNA. 我在XNA制作矢量图形游戏。 I've designed a Line class to rotate around a central point to help draw specific shapes. 我设计了一个Line类来围绕中心点旋转,以帮助绘制特定的形状。 In order to maintain a single point of truth, is there a way to pass a reference to the center of the shape to all of the lines I create, so that updating the center's position will also update the lines' positions? 为了保持单一的真实点,有没有办法将形状中心的引用传递给我创建的所有线,这样更新中心的位置也会更新线的位置? I thought something like this would work: 我认为这样的事情会起作用:

class Line
{
    private Vector2 start;
    private double length;
    private double angle;

    public Line(ref Vector2 start, double length, double angle){
        this.start = start;
        this.length = length;
        this.angle = angle;
    }
}




class Obj
{
    private Vector2 center;
    private Line[] lines;
    public Obj(){
        center = new Vector2(50,50);
        lines = new Lines[5];
        for (int i = 0; i < 5; i++){
            lines[i] = new Line(ref center,30, (i/5 * 2 * Math.PI));

        }

    }
}

but the lines do not update when I move the center. 但是当我移动中心时,线条不会更新。 What am I doing wrong? 我究竟做错了什么?

Although the struct is correctly passed by reference to Line , when you assign it internally: 虽然struct被正确引用传递到Line ,当你在内部分配给它:

public Line(ref Vector2 start, double length, double angle){
    this.start = start;
}

You are actually taking a copy of the struct . 您实际上正在获取struct副本

If you ever find yourself needing reference type semantics of struct beyond passing it to a single method then you likely need to reconsider using class . 如果您发现自己需要struct引用类型语义而不是将其传递给单个方法,那么您可能需要重新考虑使用class

You can either re-implement the type in a class or wrap the Vector2 in a class and use that: 您可以在类中重新实现类型,也可以将Vector2包装在类中并使用它:

class Vector2Class
{
    public Vector2 Centre;

    public Vector2Class(Vector2 inner)
    {
        Centre = inner;
    }
}

class Line
{
    private Vector2Class _centre;

    public Line(Vector2Class centre)
    {
        _centre = centre;    
    }
}

Be aware that you are still working against a copy, but if you share the class you'll all be working on the same copy. 请注意,您仍在使用副本,但如果您共享该类,则所有人都将使用相同的副本。

Personally, I would avoid the wrapper and make my own class for representing "centre". 就个人而言,我会避免使用包装器并将自己的类用于表示“中心”。 This is supported by the largely accepted idea that struct types should be immutable, but you seem to need to mutate the values to keep the representation true. struct类型应该是不可变的,但是你似乎需要改变值以保持表示为真。

class CentreVector<T>
{
    public <T> X { get; set; }
    public <T> Y { get; set; }
}

This only lets you share the data, it doesn't actually notify the lines that the centre has changed. 这只允许您共享数据,它实际上不会通知线路中心已更改。 For that you would need some sort of event. 为此你需要某种事件。

Edited with alternative solution 用替代解决方案编辑

The problem you're having is because Vector2 is a value type, you're correctly passing it by ref in your methods parameter but then making a local copy of it with the assignment. 您遇到的问题是因为Vector2是一个值类型,您正确地在您的方法参数中通过ref传递它,然后使用赋值创建它的本地副本。

I'm not totally sure if you could maintain a pointer to Vector2 in the way that you're thinking but you could create your own Vector2 class that would be a reference type. 我不完全确定你是否可以按照你想的方式维护指向Vector2的指针,但你可以创建自己的Vector2类作为引用类型。

class ObjectVector2
{
    public float X { get;set; }
    public float Y { get; set; }
}

I would like to suggest a slightly different way to achieve the same result by holding a reference to the obj that the lines are a part of. 我想提出一种稍微不同的方法来实现相同的结果,方法是保持对行所属的obj的引用。

class Line
{

    private Vector2 Center { get { return parent.center; } }
    private double length;
    private double angle;
    Obj parent;

    public Line(Obj parent, double length, double angle)
    {
       this.parent = parent;
       this.length = length;
       this.angle = angle;
    }
}

class Obj
{
    public Vector2 center;
    private Line[] lines;
    public Obj()
    {
        center = new Vector2(50, 50);
        lines = new Lines[5];
        for (int i = 0; i < 5; i++)
        {
           // passing the reference to this Obj in the line constructor.
           lines[i] = new Line(this, 30, (i / 5 * 2 * Math.PI));
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM