V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Neveroldmilk
V2EX  ›  .NET

邪门了,函数值传递和引用传递的结果反过来了?!

  •  
  •   Neveroldmilk · 2015-10-29 21:14:19 +08:00 · 3379 次点击
    这是一个创建于 3093 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这是 C#程序设计的例子,我在 VS2015 和 2013 上调试的输出结果和书上正好相反!我的输出是账号 001 余额 200 ,账号 002 余额 100 。
    求大侠指点!
    代码如下:

    using System;

    namespace P3_6
    {
    class Program
    {
    static void Main(string[] args)
    {
    Account a1 = new Account() { ID = "001" };
    EditAccount(a1);
    a1.Query();
    ChangeAccount(ref a1);
    a1.Query();
    }

    static void EditAccount(Account a)
        {
            a.Money = a.Money * 2;
            a = new Account() { ID = "002" };
        }
    
        static void ChangeAccount(ref Account a)
        {
            a.Money = a.Money * 2;
            a = new Account() { ID = "002" };
        }
    }
    
    class Account
    {
        public string ID;
        public decimal Money = 100;
    
        public void Query()
        {
            Console.WriteLine("账号{0} 余额{1}", ID, Money);
        }
    }
    

    }

    14 条回复    2015-10-31 06:49:47 +08:00
    domty
        1
    domty  
       2015-10-29 21:37:56 +08:00
    c#已忘干净
    (ref {param})就是引用传递的话
    结果应该就是你说的啊
    breeswish
        2
    breeswish  
       2015-10-29 21:40:00 +08:00
    你输出的是正确的
    zts1993
        3
    zts1993  
       2015-10-29 21:49:58 +08:00
    EditAccount 可以修改 a1 对象但是不能修改 a1 指向的对象。。

    我觉得你可以曝光一下是什么误人子弟的书。。
    xingo
        4
    xingo  
       2015-10-29 22:11:42 +08:00
    上面两位把我想说的说完了,我想说的是

    两个方法后面和那个 Account 类前面的那个括号能删除吗,看着好恶心哦(。
    bdbai
        5
    bdbai  
       2015-10-29 23:27:50 +08:00 via iPhone
    @xingo 你说的是 new Account() {} 的小括号?这个用于给构造函数传参的, C# 中不能省。
    msg7086
        6
    msg7086  
       2015-10-30 05:40:36 +08:00
    #5 楼 @bdbai 我们用的一定不是一个 C#。
    watzds
        7
    watzds  
       2015-10-30 09:21:44 +08:00 via Android
    如果和 java 差不多,那么 a1 其实只是一个引用, EditAccount 只能修改 a1 指向的对象,而不能修改 a1 这个引用本身
    asj
        8
    asj  
       2015-10-30 09:43:11 +08:00
    输出结果是正确的

    起始: a1 = Account 1 {id: '001', money:100}

    -> EditAccount
    Account 1 {id: '001', money:200}
    Account 1' {id: '002', money:100} //退出 EditAccount 时被回收
    a1 = Account 1 {id: '001', money:200}

    -> ChangeAccount
    Account 1 {id: '001', money:400} //退出 ChangeAccount 时被回收
    Account 2 {id: '002', money:100}
    a1 = Account 2 {id: '002', money:100}

    要得到你想要的结果,需要把
    ```
    a.Money = a.Money * 2;
    a = new Account() { ID = "002" };
    ```
    这两句的顺序互换
    jsq2627
        9
    jsq2627  
       2015-10-30 13:22:45 +08:00
    @bdbai 可以省略的。
    mx1700
        10
    mx1700  
       2015-10-30 13:26:36 +08:00
    结果是正确的。
    你可以理解为,直接传递对象的时候,其实是传递的对象引用的拷贝,他们指向同一个对象;
    而 ref 传递的是引用本身。

    所以第一个里边修改 a ,不影响外部,第二个会有影响。
    doing
        11
    doing  
       2015-10-30 16:39:38 +08:00
    c#方法参数都是值传递,只是 在基本数据类型和引用类型作为参数的时候,这个值的数据有区别:一个是具体的值,一个是地址的引用。

    然后加关键词 ref 只是把基本数据类型作为参数 值的传递方式 按照 引用类型作为参数的方式去传递数据
    bdbai
        12
    bdbai  
       2015-10-30 18:30:18 +08:00 via iPhone
    @msg7086 @jsq2627 习惯问题,少了括号反而觉得不爽。明明在调用函数。
    msg7086
        13
    msg7086  
       2015-10-30 20:19:43 +08:00
    @bdbai 明明在创建对象,怎么成调用函数了。
    bdbai
        14
    bdbai  
       2015-10-31 06:49:47 +08:00 via iPhone
    @msg7086 构造函数。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5583 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 01:36 · PVG 09:36 · LAX 18:36 · JFK 21:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.