C# 默认传递参数是 ByRef 而不是 ByVal

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9717057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:31:52  来源:igfitidea点击:

C# Passing arguments by default is ByRef instead of ByVal

c#

提问by Nime Cloud

I know the default is ByVal in C#. I used same variable names in many places and then I noticed passed values change and come back. I think I knew scope mechanism of C# wrong. Here public licenseoverrides the local licensevalues. I know I can easily rename the variable names in conflict but I would like to learn the facts about scope.

我知道默认值是 C# 中的 ByVal。我在很多地方使用了相同的变量名,然后我注意到传递的值发生了变化并回来了。我想我知道 C# 的作用域机制是错误的。这里公共许可证覆盖本地许可证值。我知道我可以轻松地重命名冲突的变量名称,但我想了解有关范围的事实。

  public static class LicenseWorks
  {
     public static void InsertLicense(License license)
     {
        license.registered = true;
        UpdateLicense(license);
     }
  }

  public partial class formMain : Form
  {
     License license;

     private void btnPay_Click(object sender, EventArgs e)
     {
          license.registered = false;
          LicenseWorks.InsertLicense(license);

          bool registered = license.registered; //Returns true!
      }
  }    

Update:I've added below as solution:

更新:我在下面添加了解决方案:

    public static void InsertLicense(License license)
    {

        license = license.Clone();
        ...
     }

采纳答案by Jon Skeet

The argument is being passed by value - but the argument isn't an object, it's a reference. That referenceis being passed by value, but any changes made to the objectvia that reference will still be seen by the caller.

参数是按值传递的 - 但参数不是object,它是一个reference。该引用是按值传递的,但通过该引用对对象所做的任何更改仍会被调用者看到。

This is very different to realpass by reference, where changes to the parameter itselfsuch as this:

这与真正的按引用传递非常不同,其中对参数本身的更改如下:

 public static void InsertLicense(ref License license)
 {
    // Change to the parameter itself, not the object it refers to!
    license = null;
 }

Now if you call InsertLicense(ref foo), it will make foonull afterwards. Without the ref, it wouldn't.

现在,如果您调用InsertLicense(ref foo),它将在foo之后变为 null。没有 ref 就不行。

For more information, see two articles I've written:

有关更多信息,请参阅我写的两篇文章:

回答by nietras

You need to learn the difference between reference typesand value types. Here I presume you are using a reference type License, which means you are actually parsing a referenceto the instance in question.

您需要了解引用类型值类型之间的区别。在这里,我假设您使用的是引用类型许可证,这意味着您实际上是在解析对相关实例的引用

See: http://msdn.microsoft.com/en-us/library/aa711899(v=vs.71).aspx

请参阅:http: //msdn.microsoft.com/en-us/library/aa711899(v=vs.71).aspx

Although, not necessarily correct a value type is often allocated on the stack or within a reference type. While reference types are always allocated on the managed heap.

虽然不一定正确,但通常在堆栈上或引用类型内分配值类型。而引用类型总是在托管堆上分配。

回答by Michel Keijzers

When passing license in InsertLicense you pass it not by value but as reference. That means when changing the registered item to true, it will change that and after returning the reference the registered item will be true.

在 InsertLicense 中传递许可证时,您不是通过值传递它,而是作为参考传递它。这意味着当将注册项更改为 true 时,它​​将更改该值,并且在返回引用后,注册项将为 true。

回答by Jeb

You are passing the licence argument by value; essentially this means you can modify any public properties of the object. However, if you reassign the reference of the licence object to a new object, i.e. if you did this:

您正在按值传递许可证参数;本质上,这意味着您可以修改对象的任何公共属性。但是,如果您将许可证对象的引用重新分配给新对象,即如果您这样做:

public static void InsertLicense(License license)      
{         
   license = new Licence();         
   UpdateLicense(license);      
}

the caller won't reference the new license object defined in the static method unless you passed it by ref.

除非您通过 ref 传递,否则调用者不会引用静态方法中定义的新许可证对象。

Remember that all parameters are passed into methods by value unless you use the ref or out keywords.

请记住,除非您使用 ref 或 out 关键字,否则所有参数都是按值传递给方法的。

回答by gt6707a

Ran across this and thought I should share what Microsoft says:

遇到这个并认为我应该分享微软所说的:

"Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference."

“不要把按引用传递的概念和引用类型的概念混为一谈,这两个概念是不一样的。一个方法参数无论是值类型还是引用类型都可以通过ref修改。没有装箱通过引用传递时属于值类型。”

MSDN: ref (C# Reference)

MSDN:参考(C# 参考)