为什么这行代码没有更新对象?

时间:2016-09-29 06:20:27

标签: c# .net methods struct value-type

鉴于有一个名为Point的类,其中包含float xfloat y组件。

class Point
{
    public double x;
    public double y;
    public Point(double x, double y)
    {
        this.x = x;
        this.y = y;
    }
    public Point()
    {
        x = y = 0;
    }
    public override string ToString()
    {
        return string.Format("({0:F2},{1:F2})", x, y);
    }
}

为什么mystery1函数没有将p1更新为(11.00,11.00),因为p.x从第一行开始是11?

{
    Point p1 = new Point(11, 22);
    Point p2 = p1;
    int n1 = 33;
    int n2 = n1;

    mystery1(p1, n1);
    Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);
    Console.WriteLine("p1 = {0}, p2 = {1}", p1, p2);

    mystery2(p2, n2);
    Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);
    Console.WriteLine("p1 = {0}, p2 = {1}", p1, p2);
}

static void mystery1(Point p, int n)
{
    n = (int)p.x;
    p = new Point(n, n);
}

static void mystery2(Point p, int n)
{
    p.x = 77;
    n = 88;
}

2 个答案:

答案 0 :(得分:1)

Point是值类型。因此,当您使用point作为参数调用方法时,您将在方法中拥有该点的新实例。因此,您要更改不在main方法中的实例上的值。

查看ref关键字:https://msdn.microsoft.com/en-us/library/0f66670z.aspx

此时,您使用new Point(n, n);创建一个新实例,您甚至可以再创建一个点实例。 你的主要方法仍然指向没有改变的旧对象。

另外,我建议您大致了解值和复杂类型之间的差异,例如:https://msdn.microsoft.com/en-us/library/34yytbws(v=vs.100).aspx 或者在这里: https://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

答案 1 :(得分:1)

在C#中,所有参数都按值传递,甚至引用。

这意味着当您将类的实例传递给方法时,您将该实例的引用作为值传递。想象一下,引用(类似于指针)只是存储在字符串中的堆栈中的实例的地址(它不是字符串,但为简单起见,我们假设如此)。现在当你改变那个字符串外面会发生什么?没什么,因为字符串只是一个值,它与您实际引用的实例没有任何关系。这听起来很奇怪,但就是这样。在<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <link rel="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css" /> </head> <body ng-app="app"> <div class="container" ng-controller="appController"> Total amount: {{TotalAmount}} <table class="table table-striped"> <tr><th>Percent</th><th>Value</th></tr> <tr ng-repeat="invoice in Data"> <td><input type="number" ng-change="percentChange($index,invoice.Percent)" ng-model="invoice.Percent" /></td> <td><input type="number" ng-change="valueChange($index,invoice.Percent)" ng-model="invoice.Value" /></td> </tr> </table> </div> </body> </html> - 方法中,您只需重新 - 将此引用分配给新实例,但只需更改该引用的,而不是引用本身。

你可以通过引用传递类来实现这一点:

msyter1

现在方法中的更改会反映到方法的外部。

static void mystery1(ref Point p, ref int n) 中存在差异且您不需要mystery2 - 类的ref - 关键字,因为您不会更改引用本身但是属性为引用的实例。但是这不适用于整数参数,它当然是值类型,因此必须由Point传递,以便在方法之外更新:

ref