在此 .net 示例中是否应该通过引用传递参数?

发布于 2024-09-02 06:46:24 字数 984 浏览 6 评论 0原文

我用过Java、C++、.Net。 (按顺序)。当在采访中被问到按值与按引用时,我在这个问题上总是做得很好......也许是因为没有人深入研究它。现在我知道我没有看到全貌。

我在看别人写的这段代码:

XmlDocument doc = new XmlDocument();
AppendX(doc); // Real name of the function is different
AppendY(doc); // ditto

当我看到这段代码时,我想:等一下,我是不是应该在 doc 前面使用一个 ref变量(并相应地修改 AppendX/Y?它按书面方式工作,但让我怀疑我是否真正理解 C# 中的 ref 关键字。

当我更多地思考这一点时,我回忆起早期的 Java 时代(大学介绍语言)。我的一个朋友看了我写的一些代码,他有一个心理障碍 - 他一直问我哪些东西是通过引用传递的,什么时候是通过值传递的,我无知的回答是这样的。 : 老兄,Java 中传递的参数只有一种,我忘了是哪一种了:)。冷静,不要过度思考,只管编码。

Java 还没有 ref 吗?然而,Java 黑客似乎效率很高。不管怎样,C++ 编码让我接触到了整个参考业务,现在我很困惑。

上面的例子中应该使用 ref 吗?

我猜测当 ref 应用于值类型:基元、枚举、结构(此列表中还有其他内容吗?)时,它会产生很大的差异。而且......当应用于对象时,它不会,因为它都是通过引用的。如果事情如此简单,那么编译器为什么不将 ref 关键字的使用限制为类型的子集。

当涉及到对象时,ref 是否起到注释的作用?好吧,我确实记得 null 可能存在问题,并且 ref 对于在方法中初始化多个元素也很有用(因为您不能使用与你会用Python做)。

谢谢。

I have used Java, C++, .Net. (in that order). When asked about by-value vs. by-ref on interviews, I have always done well on that question ... perhaps because nobody went in-depth on it. Now I know that I do not see the whole picture.

I was looking at this section of code written by someone else:

XmlDocument doc = new XmlDocument();
AppendX(doc); // Real name of the function is different
AppendY(doc); // ditto

When I saw this code, I thought: wait a minute, should not I use a ref in front of doc variable (and modify AppendX/Y accordingly? it works as written, but made me question whether I actually understand the ref keyword in C#.

As I thought about this more, I recalled early Java days (college intro language). A friend of mine looked at some code I have written and he had a mental block - he kept asking me which things are passed in by reference and when by value. My ignorant response was something like: Dude, there is only one kind of arg passing in Java and I forgot which one it is :). Chill, do not over-think and just code.

Java still does not have a ref does it? Yet, Java hackers seem to be productive. Anyhow, coding in C++ exposed me to this whole by reference business, and now I am confused.

Should ref be used in the example above?

I am guessing that when ref is applied to value types: primitives, enums, structures (is there anything else in this list?) it makes a big difference. And ... when applied to objects it does not because it is all by reference. If things were so simple, then why would not the compiler restrict the usage of ref keyword to a subset of types.

When it comes to objects, does ref serve as a comment sort of? Well, I do remember that there can be problems with null and ref is also useful for initializing multiple elements within a method (since you cannot return multiple things with the same easy as you would do in Python).

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

始终不够爱げ你 2024-09-09 06:46:24

你并不是唯一一个感到困惑的人。

默认情况下,C# 中的所有内容均按值传递 - 但在引用类型(例如 XmlDocument)的情况下,该值是一个引用。

ref 关键字用于指示参数是“按引用传递”,并且也必须在调用站点指定。 Java 没有任何等效的东西 - Java 中的所有内容都是按值传递的。

有关更多详细信息,请参阅我的有关参数传递的文章

You're not alone in being confused.

By default, everything is passed by value in C# - but in the case of a reference type (such as XmlDocument) that value is a reference.

The ref keyword is used to indicate that a parameter is "pass by reference" and it has to be specifed at the call site as well. Java doesn't have any equivalent - everything in Java is passed by value.

See my article on parameter passing for a lot more detail.

清浅ˋ旧时光 2024-09-09 06:46:24

对象类型始终通过引用传递(实际上引用是通过值传递)。整型可以通过引用或值传递。

Object types are always passed by reference (actually the reference is passed by value). Integral types may be passed by reference or value.

三生池水覆流年 2024-09-09 06:46:24

接受由 ref 传递的引用类型变量的方法可能会更改该变量所指向的内容 - 而不仅仅是修改它。

A method that accepts a reference type variable passed by ref may change the thing the variable is pointing to - not just modify it.

固执像三岁 2024-09-09 06:46:24

http://www.albahari.com/valuevsreftypes.aspx 对差异有很好的解释.Net 中的引用类型和值类型之间的关系。

http://www.albahari.com/valuevsreftypes.aspx has a great explanation of the difference between Reference Types and Value Types in .Net.

强辩 2024-09-09 06:46:24

不,不要使用 ref 关键字。您想要使用文档的内容,而不是更改文档本身。请参阅这篇文章以获取进一步说明:参考关键字

No, don't use the ref keyword. You want to use the content of the doc, not change doc itself. See this post for further explenation: ref keyword

孤单情人 2024-09-09 06:46:24

这取决于您想要 AppendX 做什么。如果是修改对象的内容,则不需要通过ref传递。如果您希望 AppendX 能够更改变量“doc”指向的对象,则您需要这样做。 “doc”已经是一个“引用类型”,相当于c++中指向对象的指针。

That depends on what you want AppendX to do. If it is modifying the contents of the object, it does not need to be passed by ref. If you wish AppendX to be able to change which object the variable "doc" points to, you need to. "doc" is already a "reference type", which is equivelant to it being a pointer to an object in c++.

小兔几 2024-09-09 06:46:24

我和一些同事争论过这个问题,最终败诉。这就是我如何学会按照他们的方式做事的。

refout 关键字的意思是“我可能/将会用新的引用替换当前的引用”。调用该方法后,该变量可能引用一个完全不同的对象。另一方面,众所周知,对于引用类型,该类型的属性可能会发生变化,如果它们很重要,则应该缓存它们。

我并不完全同意它,但有一些东西来表示“参考将改变”绝对是有意义的。

I argued this with some coworkers and ultimately lost; here's how I learned to do things their way.

The ref and out keywords mean "I may/will replace the current reference with a new reference". After calling the method, the variable might refer to a completely different object. On the other hand, it's always known that for reference types, the properties of that type might change and if they were important you should cache them.

I don't fully agree with it, but it definitely makes sense to have something to signify "the reference will change".

白云不回头 2024-09-09 06:46:24

你并不是唯一一个在 c++ 和 c# 中感到困惑和编码的人,我可以理解为什么在 c++ 中使用 & 时(不是作为批评,而是作为评论,因为这也是我生活的世界)。在传递引用的参数上,您基本上是说这是一个别名,我将在方法内部使用该别名来传递给该方法的参数。您对该参数所做的任何操作都将具有与使用该变量本身相同的效果。
所以在代码中你可以这样做:
void Foo(MyClass&arg)
{
arg = new MyClass(1);
或者

int x = new MyClass(0);
Foo(x);

int x = new MyClass(0);
void Foo()
{
   x = new MyClass(1);
}

任何一种情况下 x 现在等于 MyClass(1) (并且您有泄漏,因为您无法到达原始状态,但这不是我的观点)。我想从你的问题中你已经知道了这一点,但无论如何它都会有一个目的:)

如果你在标准中传递一个引用,那么该引用是按值传递的。它不再是别名,您对引用对象所做的所有操作都会影响该对象,但如果您对引用该对象的变量执行任何操作(例如分配一个新对象),那么这只会影响引用的副本。让我们再写一些代码

c#

MyClass x = MyClass(0);
void Foo(MyClass arg) //reference being passed by val
{
  arg = new MyClass(1);
}
Foo(x);

x still equals MyClass(0)

MyClass x = MyClass(0);
void Foo(ref MyClass arg) //passing by ref
{
  arg = new MyClass(1);
}
Foo(ref x);

x equals MyClass(1)

因此,C# 中传递的标准参数与 C++ 中传递的引用不同,但使用 ref 关键字(不鼓励这样做)可以让您接近相同的结果力学作为&在 C++ 中
&由于优化/缺乏复制,通常鼓励在 C++ 中使用,因为您只在 C# 中复制引用,这不是问题,并且仅当您确实需要传递给方法的变量的别名时(即当您可能需要时)才应使用 ref必须将新的对象实例分配给变量,而不是使用/更改对象的状态

You're not alone at being confused and coding in c++ and c# I can understand why (not ment as critisism but as a comment since that's the world I live in too) in c++ when you use & on an argument to pass a reference you are basically saying this is an alias I will use inside the method for the argument being passed to the method. Anything you do to that argument will have the same effect as if you had used the variable it self.
so in code you can do:
void Foo(MyClass& arg)
{
arg = new MyClass(1);
}

int x = new MyClass(0);
Foo(x);

or

int x = new MyClass(0);
void Foo()
{
   x = new MyClass(1);
}

in either case x now equals MyClass(1) (and you have a leak cuz there's no way you can get to the original but that's not my point). I guess from you question you knew that already but it will serve a purpose anyway :)

If you pass a reference in the standard is that the reference is passed by value. It's no longer an alias everything you do to the object being references will effect the object but if you do anything to the variable referencing the object (e.g. assigning a new object) then that will only affect the copy of the reference. Let's have some more code

c#

MyClass x = MyClass(0);
void Foo(MyClass arg) //reference being passed by val
{
  arg = new MyClass(1);
}
Foo(x);

x still equals MyClass(0)

MyClass x = MyClass(0);
void Foo(ref MyClass arg) //passing by ref
{
  arg = new MyClass(1);
}
Foo(ref x);

x equals MyClass(1)

So the standard argument passing in C# differs from passing a reference in C++ but using the ref keyword (which is not encouraged) gives you close to the same mechanics as & in c++
& in C++ is usually encouraged due to optimization/lack of copying how ever since you only copy the reference in C# that's not a concern and ref should only be used when you really need an alias for the variable being passed to the method aka when you potentially have to assign a new object instance to the variable rather than using/changing the state of an object

懵少女 2024-09-09 06:46:24

如果您之前用过 C++ 编码,那么您一定熟悉指针。 .NET 代码和 Java 中的对象引用实际上是一个指针。它只是没有明确地以语法形式编写,这使得它明显是一个指针,您应该记住它。规则并不难,任何引用类、数组、字符串或 System.Object 的对象的变量都是引用类型,并且该变量是指针。其他都是值类型,变量包含实际值。

当您将此类变量传递给方法时,您正在传递指针值。然后,该方法可以根据需要修改所指向的对象。通过引用传递指针没有任何区别,它仍然是相同的指针,指向相同的对象。

当您传递值类型的值时,这是完全不同的。如果您希望调用方法修改该值,那么您必须生成指向该值的指针。您可以通过在方法声明中使用“ref”关键字来执行此操作。

异常情况是您希望调用方法返回一个新对象的情况。换句话说,就是修改指针的值。 然后您必须使用 ref 关键字,它创建一个指向指针的指针。通常,您可以通过让方法返回对象作为方法返回值来避免这种情况。

If you've coded in C++ before then you must be familiar with pointers. An object reference in .NET code and Java is a pointer under the hood. It just isn't explicitly written in a syntax that makes it obvious that it is a pointer, you are supposed to memorize it. The rule isn't very hard, any variable that refers to an object of a class, an array, a string or System.Object is a reference type and the variable is a pointer. Anything else is a value type and the variable contains the actual value.

When you pass such a variable to a method, you are passing the pointer value. The method can then modify the pointed-to object as it sees fit. Passing the pointer by reference doesn't make any difference, it is still the same pointer, pointing to the same object.

This is entirely different when you pass a value of a value type. If you want the calling method to modify that value then you have to generate a pointer to that value. You do so by using the "ref" keyword in the method declaration.

The outlier case is where you want the calling method to return a new object. In other words, modify the pointer value. Then you have to use the ref keyword, that creates a pointer to a pointer. You'd typically avoid that by having the method return the object as the method return value.

清秋悲枫 2024-09-09 06:46:24

很多人对此感到困惑。我是这样想的。我根本不认为“ref”是“通过引用”的意思。我认为“ref”的意思是“别名”。也就是说,当你说

void M(ref int x) { x = 123; }
void N(int z) { ... }
...
int y = 456;
M(ref y);
N(y);

“ref y”的意思是“请将相应的形式参数x设置为变量y的别名”。也就是说,x 和 y 现在都是相同存储位置的变量。当您写入 x 时,您实际上是在写入 y,因为 x 是 y 的另一个名称。

当您在没有 ref 的情况下传递时,如在 N(y) 中,您是在说“y 和 z 是两个不同的变量,因此 z 以与 y 相同的内容开始其生命周期”。

一旦你开始这样思考,你就不必担心传递引用和传递值,等等,这一切都非常令人困惑。关键区别在于,普通传递创建一个新变量并使用参数对其进行初始化,而 ref 为现有变量创建别名

我希望我们使用“alias”而不是“ref”;情况会更加清楚。

Lots of people are confused by this. Here's how I think of it. I don't think of "ref" as meaning "by reference" at all. I think of "ref" as meaning "alias". That is, when you say

void M(ref int x) { x = 123; }
void N(int z) { ... }
...
int y = 456;
M(ref y);
N(y);

what that "ref y" means is "please make the corresponding formal parameter x an alias to the variable y". That is, x and y now are both variables for the same storage location. When you write to x, you're writing to y because x is another name for y.

When you pass without ref, as in N(y) you're saying "y and z are two different variables such that z begins its lifetime with the same contents as y".

Once you start thinking about it like that you don't have to worry about pass-by-ref vs pass-by-value, blah blah blah, it's all very confusing. The key difference is that normal passing creates a new variable and initializes it with the argument, whereas ref makes an alias to an existing variable.

I wish we'd used "alias" instead of "ref"; it would have been much more clear.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文