77.函数传进类作参数打印结果

77.函数传进类作参数打印结果


77.1 题目

class TestClass
{
    public int i = 0;
}

static void TestFun(TestClass obj)
{
    obj = new TestClass();
    obj.i = 10;
}

static void Main(string[] args)
{
    TestClass t = new TestClass();
    TestFun(t);
    Console.WriteLine(t.i);
}

代码的打印结果是什么?要如何修改才能让打印结果变成10?使用三种方法修改。


77.2 深入解析

打印结果

代码的打印结果是 0。这是因为 TestFun 方法内部的 obj 是一个局部变量,虽然它被赋值为一个新的 TestClass 对象,但这并不会影响到传入的原始对象 t

修改方法

方法一:通过引用传递对象

使用 ref 关键字来传递对象引用,使方法内部的更改能够影响到调用者。

class TestClass
{
    public int i = 0;
}

static void TestFun(ref TestClass obj)
{
    obj = new TestClass();
    obj.i = 10;
}

static void Main(string[] args)
{
    TestClass t = new TestClass();
    TestFun(ref t);
    Console.WriteLine(t.i); // 输出 10
}

方法二:修改对象的属性值

直接在方法中修改传入对象的属性,而不是重新分配对象。

class TestClass
{
    public int i = 0;
}

static void TestFun(TestClass obj)
{
    obj.i = 10;
}

static void Main(string[] args)
{
    TestClass t = new TestClass();
    TestFun(t);
    Console.WriteLine(t.i); // 输出 10
}

方法三:返回修改后的对象

让方法返回一个新的对象,并在调用时接受返回值。

class TestClass
{
    public int i = 0;
}

static TestClass TestFun(TestClass obj)
{
    obj = new TestClass();
    obj.i = 10;
    return obj;
}

static void Main(string[] args)
{
    TestClass t = new TestClass();
    t = TestFun(t);
    Console.WriteLine(t.i); // 输出 10
}

方法四:通过 out 传递对象

使用 out 关键字来传递对象引用,使方法内部的更改能够影响到调用者。

class TestClass
{
    public int i = 0;
}

static void TestFun(out TestClass obj)
{
    obj = new TestClass();
    obj.i = 10;
}

static void Main(string[] args)
{
    TestClass t;
    TestFun(out t);
    Console.WriteLine(t.i); // 输出 10
}

77.3 答题示例

打印结果:代码输出 0。原因是C#中对象引用作为参数传递时,传递的是引用的副本,方法内重新赋值 obj = new TestClass() 只会改变副本指向的对象,不会影响原始引用 t

三种修改方法

  1. 使用 ref 关键字(推荐):

    static void TestFun(ref TestClass obj) {  
        obj = new TestClass();  
        obj.i = 10;  
    }  
    // 调用时需显式加 ref  
    TestFun(ref t);  
    

    通过引用传递,使方法内外引用同一对象地址。

  2. 直接修改属性值(最简洁):

    static void TestFun(TestClass obj) {  
        obj.i = 10; // 不创建新对象,直接修改传入对象的属性  
    }  
    

    对象引用的副本仍指向原始对象 t

  3. 返回新对象并赋值(语义明确):

    static TestClass TestFun(TestClass obj) {  
        return new TestClass { i = 10 };  
    }  
    // 调用时接收返回值  
    t = TestFun(t);  
    

    通过返回值覆盖原始引用。”


77.4 关键词联想

  • 值类型 vs 引用类型
  • 引用传递(ref/out
  • 方法参数传递机制
  • 对象引用副本
  • 堆内存与栈内存
  • 不可变对象模式
  • C# 参数修饰符(in/ref/out
  • 方法返回值
  • 副作用(Side Effect)
  • 代码可读性与维护性


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏