在C#中通过引用或值传递对象

在C#中,我一直认为非原始变量是通过引用传递的,原始值是通过值传递的。

所以当传递给方法的任何非原始对象时,对方法中的对象做的任何事情都会影响被传递的对象。 (C#101的东西)

但是,我注意到,当我传递一个System.Drawing.Image对象时,这似乎并不是这种情况? 如果我将system.drawing.image对象传递给另一个方法,并将图像加载到该对象上,那么让该方法超出范围并返回调用方法,该图像不会加载到原始对象上?

为什么是这样?


对象根本不通过。 默认情况下,参数被计算并且其值通过值被传递为您调用的方法参数的初始值。 现在重要的一点是,该值是引用类型的参考 - 一种获取对象(或null)的方法。 该对象的更改将从调用者可见。 但是,如果使用按值传递(这是所有类型的默认值),则更改参数的值以引用不同的对象将不可见。

如果要使用传递ref ,则无论参数类型是值类型还是引用类型,都必须使用outref 。 在这种情况下,实际上变量本身是通过引用传递的,所以参数使用与参数相同的存储位置 - 并且调用者可以看到参数本身的变化。

所以:

public void Foo(Image image)
{
    // This change won't be seen by the caller: it's changing the value
    // of the parameter.
    image = Image.FromStream(...);
}

public void Foo(ref Image image)
{
    // This change *will* be seen by the caller: it's changing the value
    // of the parameter, but we're using pass by reference
    image = Image.FromStream(...);
}

public void Foo(Image image)
{
    // This change *will* be seen by the caller: it's changing the data
    // within the object that the parameter value refers to.
    image.RotateFlip(...);
}

我有一篇文章详细介绍了这方面的内容。 基本上,“通过参考”并不意味着你的想法。


还有一个代码示例来展示这一点:

void Main()
{


    int k = 0;
    TestPlain(k);
    Console.WriteLine("TestPlain:" + k);

    TestRef(ref k);
    Console.WriteLine("TestRef:" + k);

    string t = "test";

    TestObjPlain(t);
    Console.WriteLine("TestObjPlain:" +t);

    TestObjRef(ref t);
    Console.WriteLine("TestObjRef:" + t);
}

public static void TestRef(ref int i)
{
    i = 5;
}

public  static void TestPlain(int i)
{
    i = 5;
}

public static void TestObjRef(ref string s)
{
    s = "TestObjRef";
}

public static void TestObjPlain(string s)
{
    s = "TestObjPlain";
}

输出:

TestPlain:0

TestRef:5

TestObjPlain:测试

TestObjRef:TestObjRef


当你这样做时,我想它更清晰。 我建议下载LinkPad来测试这样的事情。

void Main()
{
    var Person = new Person(){FirstName = "Egli", LastName = "Becerra"};

    //Will update egli
    WontUpdate(Person);
    Console.WriteLine("WontUpdate");
    Console.WriteLine($"First name: {Person.FirstName}, Last name: {Person.LastName}n");

    UpdateImplicitly(Person);
    Console.WriteLine("UpdateImplicitly");
    Console.WriteLine($"First name: {Person.FirstName}, Last name: {Person.LastName}n");

    UpdateExplicitly(ref Person);
    Console.WriteLine("UpdateExplicitly");
    Console.WriteLine($"First name: {Person.FirstName}, Last name: {Person.LastName}n");
}

//Class to test
public class Person{
    public string FirstName {get; set;}
    public string LastName {get; set;}

    public string printName(){
        return $"First name: {FirstName} Last name:{LastName}";
    }
}

public static void WontUpdate(Person p)
{
    //New instance does jack...
    var newP = new Person(){FirstName = p.FirstName, LastName = p.LastName};
    newP.FirstName = "Favio";
    newP.LastName = "Becerra";
}

public static void UpdateImplicitly(Person p)
{
    //Passing by reference implicitly
    p.FirstName = "Favio";
    p.LastName = "Becerra";
}

public static void UpdateExplicitly(ref Person p)
{
    //Again passing by reference explicitly (reduntant)
    p.FirstName = "Favio";
    p.LastName = "Becerra";
}

这应该输出

WontUpdate

名:Egli,姓:Becerra

UpdateImplicitly

名:Favio,姓:Becerra

UpdateExplicitly

名:Favio,姓:Becerra

链接地址: http://www.djcxy.com/p/471.html

上一篇: Passing Objects By Reference or Value in C#

下一篇: Javascript by reference vs. by value