简体   繁体   English

通过引用传递与通过分配传递? C# 与 Python

[英]Pass by reference vs Pass by assignment? C# vs Python

I am working concurrently in C# and in Python.我同时在 C# 和 Python 工作。

Is there a difference, in terms of what is being created in memory, between passing a reference type in C#, and passing (by assignment) in Python?就 memory 中创建的内容而言,在 C# 中传递引用类型和在 Python 中传递(通过赋值)之间是否有区别? It seems in either case, if the variable is changed* in the function, it is changed in the outside scope as well.似乎在任何一种情况下,如果变量在 function 中更改*,它也会在外部 scope 中更改。

(*) of course in Python it must be mutable for this to occur. (*) 当然在 Python 中它必须是可变的才能发生。 An immutable object cannot be changed - but that is another topic.不可更改的 object 无法更改 - 但这是另一个主题。

Are we basically just talking different terminology for the same process, or is there a conceptual difference to be learned here, in terms of the underlying mechanism in memory?就 memory 中的底层机制而言,我们基本上只是在谈论同一个过程的不同术语,还是在这里需要学习概念上的差异?

First, all arguments are passed by value by default in C#.首先,arguments在C#中默认都是传值的。 This has nothing to do with the type being a reference type or a value type, both behave exactly the same way.这与类型是引用类型或值类型无关,两者的行为方式完全相同。

Now, the question is, what is a variable?现在,问题是,什么是变量? A variable is a placeholder for a value , nothing more.变量的占位符,仅此而已。 When a variabe is passed by copy, a copy of the value is made.当通过副本传递变量时,会生成该副本

And what is the value stored in a variable?存储在变量中的值是什么? Well, if the type of the variable is a reference type, the value is basically the memory address of the object its referencing.那么,如果变量的类型是引用类型,那么值基本上就是它引用的object的memory地址。 If its a value type, then the value is the objet itself.如果它是一个值类型,那么这个值就是对象本身。

So when you say:所以当你说:

It seems in either case, if the variable is changed* in the function, it is changed in the outside scope as well.似乎在任何一种情况下,如果变量在 function 中更改*,它也会在外部 scope 中更改。

That is deeply wrong because you seem to me be mixing up the type of the argument with how it is passed along:这是非常错误的,因为在我看来,您似乎将论点的类型与它的传递方式混为一谈:

First example:第一个例子:

var a = new object();
Foo(a);
var isNull = ReferenceEquals(a, null); //false!

void Foo(object o) { o = null; }

Here, a refence typed variable a is passed by value, a copy is made and then inside Foo its reassigned to null .在这里,一个引用类型的变量a按值传递,制作一个副本,然后在Foo内部将其重新分配给null a doesn't care a copy is reasigned inside Foo , it will still point to the same object. a不在乎副本Foo中重新分配,它仍将指向相同的 object。

Things of course change if you pass the argument by reference:如果您通过引用传递参数,事情当然会改变:

var a = new object();
Foo(ref a);
var isNull = ReferenceEquals(a, null); //true!

void Foo(ref object o) { o = null; }

Now you are not making a copy of a named o , you are passing a itself with an alias named o .现在你不是在复制a名为o的副本,而是在传递a名为o的别名。

Things behave exactly the same with value types:值类型的行为完全相同:

var a = 1;
Foo(a);
var isNull = 1 == 0; //false!

void Foo(int i) { i = 0; }

And

var a = 1;
Foo(ref a);
var isNull = 1 == 0; //true!

void Foo(ref int i) { i = 0; }

The difference between value types and reference types when you pass it a long by value is due to what the value of the variable is.当您通过值传递 long 时,值类型和引用类型之间的区别在于变量的值是什么。 Like we said before, reference typed variables store the address, so even if you pass along a copy, the copy points to the same object, so any changes in the object are visible from both variables:就像我们之前说的,引用类型变量存储地址,所以即使你传递一个副本,副本指向同一个 object,所以 object 中的任何更改都可以从两个变量中看到:

var ii = new List<int>();
Foo(ii);
var b = ii.Count == 1; //true!

void Foo(List<int> list) { list.Add(1); } 

But with value types, the value is the object itself, so you are passing along a copy of the object, and you are therefore modifying a copy :但是对于值类型,值是 object 本身,因此您传递的是 object 的副本,因此您正在修改副本

struct MutableStruct
{
    public int I { get; set; }
}

var m = new mutableStruct();
Foo(m);
var b = m.I == 1; //false!

void Foo(MutableStruct mutableStruct) { mutableStruct.I = 1; } 

Does this make things clearer?这会让事情变得更清楚吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM