C#隐式更新传递给方法的参数,没有返回类型,也没有out或ref用法

Bri*_*den 5 c#

这对我来说非常时髦,显然开发人员应该使用关键字out但我不相信这甚至可以工作:

public BusinessResponse<MyResultType> MyMethod(){

    BusinessResponse<MyResultType> res = new BusinessResponse<MyResultType>();
    ProcessResult(res);

    return res; //this has the values set by ProcessResult!!! How?
}

private void ProcessResult(BusinessResponse<MyResultType> result)
{
    result.State = BusinessResponseState.Success;
    //set some other stuff in the result argument
}
Run Code Online (Sandbox Code Playgroud)

我的同事说这被称为"深度参考",我不敢相信这在C#中起作用.我会重构使用outaka private void ProcessResult(out BusinessResponse<MyResultType> result)但我仍然想知道为什么这段代码有效.

UPDATE

所以看起来我不正确,这段代码很好.似乎情绪是,作为C#开发人员,我应该立即知道,因为传递给processResult的参数是堆上的引用类型,通过值传入引用本身的副本,并且复制的引用仍然指向同一个对象.

Jon*_*art 11

当然在你的情况下BusinessResponse<T>是一个class,也称为"参考类型".引用类型(对象)总是在C#中"通过引用"传递(类似于好的C中的指针)1.

这意味着无论你如何传递引用,它仍然指的是内存中的一个实例.这意味着无论你如何引用它,你总是修改同一个副本.

1 - 这不完全正确.实际发生的是引用(变量)按值传递.当函数接收到此引用时(再次,想到托管堆上某个对象的指针),它将引用同一个对象.但是,引用本身在传入时被复制.

我们使用的另一种变量是"值类型".这是structS,以及所有像元的char,bool,int等,这些都是意料之中总是传递由值,这意味着一份拷贝每次分配一个值类型的新变量(包括它传递给函数)时间.要通过函数调用修改这些,您必须使用refout关键字.

那么什么时候使用ref引用类型?

当您想要更改变量引用的实例时:

public class Foo {
    public string Name { get; private set; }
    public Foo(string name) {
        Name = name;
    }
}

public class Program {

    public static void Example(ref Foo f) {
        // This will print "original"
        Console.WriteLine("Example() was given {0}", f.Name);

        // We assign a new instance to the reference which was
        // passed by reference
        f = new Foo("replacement");
    } 

    public static void Main() {
        Foo f;                       // This variable is a "reference" to a Foo

        f = new Foo("original");     // We assign a new instance to that variable

        Example(ref f);

        // This will print "replacement"
        Console.WriteLine("After calling Example(), f is {0}", f.Name);
    }

}
Run Code Online (Sandbox Code Playgroud)

  • _"最好使用关键字out或ref以获得更好的可读性吗?"_绝对不是!使用'out'的唯一时间是,如果您打算在未初始化的情况下传递参数,然后直接在方法内分配该参数.您以相同的方式使用'ref',除了在传入之前初始化参数以及在方法中使用的初始值.你拥有的代码完全符合它的要求.你不是在传递一个新的对象; 你只是修改你传入的对象.因为它是一个引用类型对象,它的工作方式与你应该期望的完全相同. (2认同)
  • @BrianOgden当一个引用类型(对象)与*`ref` /`out`一起传递时,你传递一个对该引用的引用,(或指向你的局部变量的指针).因此,当在被调用函数中分配该引用(新的/不同的对象)时,调用函数中的原始引用(局部变量)受到影响. (2认同)