“ref”和“ref”有什么区别? 和“出”; 关键词?

发布于 2024-07-10 21:57:02 字数 220 浏览 15 评论 0原文

我正在创建一个函数,我需要在其中传递一个对象,以便该函数可以修改它。 ?

public void myFunction(ref MyClass someClass)

public void myFunction(out MyClass someClass)

我应该使用哪个以及为什么

I'm creating a function where I need to pass an object so that it can be modified by the function. What is the difference between:

public void myFunction(ref MyClass someClass)

and

public void myFunction(out MyClass someClass)

Which should I use and why?

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

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

发布评论

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

评论(28

固执像三岁 2024-07-17 21:57:02

ref告诉编译器该对象在进入函数之前被初始化,而out告诉编译器该对象将在函数内部初始化。

因此,虽然 ref 是双向的,但 out 是仅输出的。

ref tells the compiler that the object is initialized before entering the function, while out tells the compiler that the object will be initialized inside the function.

So while ref is two-ways, out is out-only.

神妖 2024-07-17 21:57:02

ref 修饰符意味着:

  1. 该值已经设置并且
  2. 该方法可以读取和修改它。

out 修饰符意味着:

  1. Value 未设置,并且在设置之前无法通过方法读取。
  2. 该方法必须在返回之前设置它。

The ref modifier means that:

  1. The value is already set and
  2. The method can read and modify it.

The out modifier means that:

  1. The Value isn't set and can't be read by the method until it is set.
  2. The method must set it before returning.
雨的味道风的声音 2024-07-17 21:57:02

假设 Dom 出现在 Peter 的小隔间,查看有关 TPS 报告的备忘录。

如果 Dom 是一个参考论点,他就会有一份备忘录的打印副本。

如果多姆不同意,他会让彼得打印一份新的备忘录供他随身携带。

Let's say Dom shows up at Peter's cubicle about the memo about the TPS reports.

If Dom were a ref argument, he would have a printed copy of the memo.

If Dom were an out argument, he'd make Peter print a new copy of the memo for him to take with him.

纸短情长 2024-07-17 21:57:02

我将尝试解释一下:

我认为我们理解值类型如何工作? 值类型有(int、long、struct 等)。 当您将它们发送到没有 ref 命令的函数时,它会复制数据。 您在函数中对该数据所做的任何操作都只会影响副本,而不影响原始数据。 ref 命令发送实际数据,任何更改都会影响函数外部的数据。

好的,回到令人困惑的部分,引用类型:

让我们创建一个引用类型:

List<string> someobject = new List<string>()

当您新建 someobject 时,会创建两个部分:

  1. 保存 someobject 数据的内存块。
  2. 对该块的引用(指针)
    数据的。

现在,当您将某个对象发送到没有引用的方法中时,它会复制引用指针,而不是数据。 现在你有了这样的结果:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

两个引用指向同一个对象。 如果您使用reference2修改某个对象的属性,它将影响reference1指向的相同数据。

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

如果您清空引用 2 或将其指向新数据,则不会影响引用 1 或引用 1 指向的数据。

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

现在,当您通过 ref 向方法发送 someobject 时会发生什么?
某个对象实际引用被发送到该方法。 因此,您现在只有一个对数据的引用:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

但这意味着什么? 它的行为与不通过 ref 发送某个对象完全相同,除了以下两点之外:

1)当您清空方法内部的引用时,它将清空方法外部的引用。

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) 您现在可以将引用指向完全不同的数据位置,并且函数外部的引用现在将指向新的数据位置。

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

I am going to try my hand at an explanation:

I think we understand how the value types work right? Value types are (int, long, struct etc.). When you send them in to a function without a ref command it COPIES the data. Anything you do to that data in the function only affects the copy, not the original. The ref command sends the ACTUAL data and any changes will affect the data outside the function.

Ok on to the confusing part, reference types:

Lets create a reference type:

List<string> someobject = new List<string>()

When you new up someobject, two parts are created:

  1. The block of memory that holds data for someobject.
  2. A reference (pointer) to that block
    of data.

Now when you send in someobject into a method without ref it COPIES the reference pointer, NOT the data. So you now have this:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

Two references pointing to the same object. If you modify a property on someobject using reference2 it will affect the same data pointed to by reference1.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

If you null out reference2 or point it to new data it will not affect reference1 nor the data reference1 points to.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

Now what happens when you send someobject by ref to a method?
The actual reference to someobject gets sent to the method. So you now have only one reference to the data:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

But what does this mean? It acts exactly the same as sending someobject not by ref except for two main thing:

1) When you null out the reference inside the method it will null the one outside the method.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) You can now point the reference to a completely different data location and the reference outside the function will now point to the new data location.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true
淤浪 2024-07-17 21:57:02

引用

只要能够满足您的要求,您就应该优先使用 out

ref is in and out.

You should use out in preference wherever it suffices for your requirements.

时光倒影 2024-07-17 21:57:02

out:

在 C# 中,一种方法只能返回一个值。 如果您想返回多个值,可以使用 out 关键字。 out 修饰符以引用返回的形式返回。 最简单的答案是使用关键字“out”从方法中获取值。

  1. 您不需要在调用函数中初始化该值。
  2. 必须在被调用的函数中赋值,否则编译器会报错。

ref:

在 C# 中,当您将 int、float、double 等值类型作为实参传递给方法参数时,它是按值传递的。 因此,如果修改参数值,不会影响方法调用中的参数。 但如果你用“ref”关键字标记参数,它将反映在实际变量中。

  1. 您需要在调用函数之前初始化变量。
  2. 不强制为方法中的 ref 参数分配任何值。 如果你不改变这个值,为什么需要将其标记为“ref”?

out:

In C#, a method can return only one value. If you like to return more than one value, you can use the out keyword. The out modifier return as return-by-reference. The simplest answer is that the keyword “out” is used to get the value from the method.

  1. You don't need to initialize the value in the calling function.
  2. You must assign the value in the called function, otherwise the compiler will report an error.

ref:

In C#, when you pass a value type such as int, float, double etc. as an argument to the method parameter, it is passed by value. Therefore, if you modify the parameter value, it does not affect argument in the method call. But if you mark the parameter with “ref” keyword, it will reflect in the actual variable.

  1. You need to initialize the variable before you call the function.
  2. It’s not mandatory to assign any value to the ref parameter in the method. If you don’t change the value, what is the need to mark it as “ref”?
小矜持 2024-07-17 21:57:02

ref 表示 ref 参数中的值已经设置,该方法可以读取和修改它。
使用ref关键字就等于说调用者负责初始化参数的值。


out告诉编译器对象的初始化是由
函数,函数必须分配给 out 参数。
不允许将其保留为未分配状态。

https://www.codemaggot.com/ref-and-out-keywords/

ref means that the value in the ref parameter is already set, the method can read and modify it.
Using the ref keyword is the same as saying that the caller is responsible for initializing the value of the parameter.


out tells the compiler that the initialization of object is the responsibility of
the function, the function has to assign to the out parameter.
It's not allowed to leave it unassigned.

https://www.codemaggot.com/ref-and-out-keywords/

迷乱花海 2024-07-17 21:57:02

扩展 Dog、Cat 的例子。 第二个带有 ref 的方法更改调用者引用的对象。 因此“猫”!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

Extending the Dog, Cat example. The second method with ref changes the object referenced by the caller. Hence "Cat" !!!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }
风苍溪 2024-07-17 21:57:02

refout 的行为类似,但存在以下差异。

  • ref 变量在使用前必须初始化。 out 变量可以在不赋值的情况下使用
  • out 参数必须被使用它的函数视为未赋值的值。 因此,我们可以在调用代码中使用已初始化的out参数,但该值在函数执行时会丢失。

ref and out behave similarly except following differences.

  • ref variable must be initialized before use. out variable can be used without assignment
  • out parameter must be treated as an unassigned value by the function that uses it. So, we can use initialized out parameter in the calling code, but the value will be lost when the function executes.
眸中客 2024-07-17 21:57:02

由于您传递的是引用类型(类),因此无需使用 ref 因为默认情况下仅传递对实际对象的引用,因此您总是会更改引用后面的对象。

示例:

public void Foo()
{
    MyClass myObject = new MyClass();
    myObject.Name = "Dog";
    Bar(myObject);
    Console.WriteLine(myObject.Name); // Writes "Cat".
}

public void Bar(MyClass someObject)
{
    someObject.Name = "Cat";
}

只要传入一个类,如果您想更改方法内的对象,就不必使用 ref

Since you're passing in a reference type (a class) there is no need use ref because per default only a reference to the actual object is passed and therefore you always change the object behind the reference.

Example:

public void Foo()
{
    MyClass myObject = new MyClass();
    myObject.Name = "Dog";
    Bar(myObject);
    Console.WriteLine(myObject.Name); // Writes "Cat".
}

public void Bar(MyClass someObject)
{
    someObject.Name = "Cat";
}

As long you pass in a class you don't have to use ref if you want to change the object inside your method.

最近可好 2024-07-17 21:57:02

对于那些通过例子学习的人(比如我),这是Anthony Kolesov 所说的

我创建了一些 ref、out 和其他的最小示例来说明这一点。 我不讨论最佳实践,只是举例来理解差异。

https://gist.github.com/2upmedia/6d98a57b68d849ee7091

For those that learn by example (like me) here's what Anthony Kolesov is saying.

I've created some minimal examples of ref, out, and others to illustrate the point. I'm not covering best practices, just examples to understand the differences.

https://gist.github.com/2upmedia/6d98a57b68d849ee7091

美人迟暮 2024-07-17 21:57:02

对于那些寻求简洁答案的人。

refout 关键字都用于传递引用

<小时>

ref关键字的变量必须有一个值或者必须引用一个对象
null 传递之前。

<小时>

ref不同,out关键字的变量必须有一个值或者必须
引用一个对象或null之后它的传递以及不需要
传递之前拥有一个值或引用一个对象。


For those looking concise answer.

Both ref and out keywords are used to pass-by-reference.


A variable of ref keyword must have a value or must refer to an object
or null before its passing.


Unlike ref, a variable of out keyword must have a value or must
refer to an object or null after its passing as well as no need
to have a value or refer to an object before passing.

盗梦空间 2024-07-17 21:57:02

“Baker”

这是因为第一个将您的字符串引用更改为指向“Baker”。 更改引用是可能的,因为您通过 ref 关键字传递了它(=> 对字符串引用的引用)。
第二个调用获取字符串引用的副本。

字符串一开始看起来有些特别。 但 string 只是一个引用类,如果您定义了 s ,

string s = "Able";

那么 s 就是对包含文本“Able”的字符串类的引用!
对同一变量的另一个赋值 via

s = "Baker";

不会更改原始字符串,而只是创建一个新实例并让 s 指向该实例!

您可以使用以下小代码示例进行尝试:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);

您期望什么?
您将得到的仍然是“Able”,因为您只是将 s 中的引用设置为另一个实例,而 s2 指向原始实例。

编辑:
string 也是不可变的,这意味着根本没有任何方法或属性可以修改现有的字符串实例(您可以尝试在文档中找到一个,但您不会找到任何:-))。 所有字符串操作方法都会返回一个新的字符串实例! (这就是为什么使用 StringBuilder 类时通常会获得更好的性能)

"Baker"

That's because the first one changes your string-reference to point to "Baker". Changing the reference is possible because you passed it via the ref keyword (=> a reference to a reference to a string).
The Second call gets a copy of the reference to the string.

string looks some kind of special at first. But string is just a reference class and if you define

string s = "Able";

then s is a reference to a string class that contains the text "Able"!
Another assignment to the same variable via

s = "Baker";

does not change the original string but just creates a new instance and let s point to that instance!

You can try it with the following little code example:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);

What do you expect?
What you will get is still "Able" because you just set the reference in s to another instance while s2 points to the original instance.

EDIT:
string is also immutable which means there is simply no method or property that modifies an existing string instance (you can try to find one in the docs but you won't fins any :-) ). All string manipulation methods return a new string instance! (That's why you often get a better performance when using the StringBuilder class)

吃兔兔 2024-07-17 21:57:02

输出:
return 语句可用于从函数中仅返回一个值。 但是,使用输出参数,您可以从函数返回两个值。 输出参数与引用参数类似,只不过它们将数据从方法中传输出来而不是传入方法中。

以下示例说明了这一点:

using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValue(out int x )
      {
         int temp = 5;
         x = temp;
      }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;

         Console.WriteLine("Before method call, value of a : {0}", a);

         /* calling a function to get the value */
         n.getValue(out a);

         Console.WriteLine("After method call, value of a : {0}", a);
         Console.ReadLine();

      }
   }
}

参考:
引用参数是对变量内存位置的引用。 当您通过引用传递参数时,与值参数不同,不会为这些参数创建新的存储位置。 引用参数表示与提供给方法的实际参数相同的内存位置。

在 C# 中,可以使用 ref 关键字声明引用参数。 以下示例演示了这一点:

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* save the value of x */
         x = y;   /* put y into x */
         y = temp; /* put temp into y */
       }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;
         int b = 200;

         Console.WriteLine("Before swap, value of a : {0}", a);
         Console.WriteLine("Before swap, value of b : {0}", b);

         /* calling a function to swap the values */
         n.swap(ref a, ref b);

         Console.WriteLine("After swap, value of a : {0}", a);
         Console.WriteLine("After swap, value of b : {0}", b);

         Console.ReadLine();

      }
   }
}

Out:
A return statement can be used for returning only one value from a function. However, using output parameters, you can return two values from a function. Output parameters are like reference parameters, except that they transfer data out of the method rather than into it.

The following example illustrates this:

using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValue(out int x )
      {
         int temp = 5;
         x = temp;
      }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;

         Console.WriteLine("Before method call, value of a : {0}", a);

         /* calling a function to get the value */
         n.getValue(out a);

         Console.WriteLine("After method call, value of a : {0}", a);
         Console.ReadLine();

      }
   }
}

ref:
A reference parameter is a reference to a memory location of a variable. When you pass parameters by reference, unlike value parameters, a new storage location is not created for these parameters. The reference parameters represent the same memory location as the actual parameters that are supplied to the method.

In C#, you declare the reference parameters using the ref keyword. The following example demonstrates this:

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* save the value of x */
         x = y;   /* put y into x */
         y = temp; /* put temp into y */
       }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;
         int b = 200;

         Console.WriteLine("Before swap, value of a : {0}", a);
         Console.WriteLine("Before swap, value of b : {0}", b);

         /* calling a function to swap the values */
         n.swap(ref a, ref b);

         Console.WriteLine("After swap, value of a : {0}", a);
         Console.WriteLine("After swap, value of b : {0}", b);

         Console.ReadLine();

      }
   }
}
濫情▎り 2024-07-17 21:57:02

除了允许您将其他人的变量重新分配给类的不同实例、返回多个值等之外,使用 refout 还可以让其他人知道您的内容需要他们以及您打算如何处理他们提供的变量

  • 不需要 refout如果您要做的只是修改在参数 someClass 中传递的 MyClass 实例内部的内容。

    • 无论您使用 refout 还是什么都不使用,调用方法都会看到诸如 someClass.Message = "Hello World" 之类的变化
    • myFunction(someClass) 中写入 someClass = new MyClass() 会替换 someClass范围内看到的对象。仅 code>myFunction 方法。 调用方法仍然知道它创建并传递给您的方法的原始 MyClass 实例
  • 需要 refout< /code> 如果您打算将 someClass 替换为一个全新的对象,并希望调用方法看到您的更改

    • myFunction(out someClass) 中写入 someClass = new MyClass() 会更改调用 myFunction 的方法所看到的对象

存在其他程序员

,他们想知道您将如何处理他们的数据。 想象一下您正在编写一个将被数百万开发人员使用的库。 您希望他们知道当他们调用您的方法时您将如何处理他们的变量

  • Using ref 声明“当您调用我的方法时传递分配给某个值的变量。请注意,我可能会在我的方法过程中将其完全更改为其他内容,不要指望在我完成后您的变量会指向旧对象”

  • Using out 声明“将占位符变量传递给我的方法,它是否有值并不重要;编译器会强制我赋值;我绝对保证在调用我的方法之前,变量所指向的对象在我完成时会有所不同

说一句,在 C#7.2 中,有一个in 修饰符也是如此

,这可以防止该方法将传入的实例交换为不同的实例。 可以将其视为对数百万开发人员说“将您的原始变量引用传递给我,我保证不会将您精心制作的数据交换为其他内容”。 in 有一些特殊性,在某些情况下,例如可能需要隐式转换以使您的 Short 与 in int 兼容,编译器将暂时生成 int,加宽你的不足之处,通过参考传递并完成。 它可以做到这一点,因为你已经声明你不会搞乱它。


微软通过数字类型上的 .TryParse 方法做到了这一点:

int i = 98234957;
bool success = int.TryParse("123", out i);

通过将参数标记为 out,他们在这里主动声明“我们肯定将把您精心设计的值 98234957 更改为其他值”

当然,对于解析值类型之类的事情,他们有点必须这样做,因为如果不允许解析方法将值类型交换为其他值,它就不会工作得很好..但是想象一下您正在创建的某个库中有一些虚构的方法:

public void PoorlyNamedMethod(out SomeClass x)

您可以看到它是一个out,因此您可以知道如果您花几个小时处理数字,就会创建完美的方法SomeClass:

SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);

嗯,那是浪费时间,花了那么多时间来上完美的课。 它肯定会被扔掉并被 PoorlyNamedMethod 取代

As well as allowing you to reassign someone else's variable to a different instance of a class, return multiple values etc, using ref or out lets someone else know what you need from them and what you intend to do with the variable they provide

  • You don't need ref or out if all you're going to do is modify things inside the MyClass instance that is passed in the argument someClass.

    • The calling method will see changes like someClass.Message = "Hello World" whether you use ref, out or nothing
    • Writing someClass = new MyClass() inside myFunction(someClass) swaps out the object seen by the someClass in the scope of the myFunction method only. The calling method still knows about the original MyClass instance it created and passed to your method
  • You need ref or out if you plan on swapping the someClass out for a whole new object and want the calling method to see your change

    • Writing someClass = new MyClass() inside myFunction(out someClass) changes the object seen by the method that called myFunction

Other programmers exist

And they want to know what you're going to do with their data. Imagine you're writing a library that will be used by millions of developers. You want them to know what you're going to do with their variables when they call your methods

  • Using ref makes a statement of "Pass a variable assigned to some value when you call my method. Be aware that I might change it out for something else entirely during the course of my method. Do not expect your variable to be pointing to the old object when I'm done"

  • Using out makes a statement of "Pass a placeholder variable to my method. It doesn't matter whether it has a value or not; the compiler will force me to assign it to a new value. I absolutely guarantee that the object pointed to by your variable before you called my method, will be different by the time I'm done

By the way, in C#7.2 there's an in modifier too

And that prevents the method from swapping out the passed in instance for a different instance. Think of it like saying to those millions of developers "pass me your original variable reference, and I promise not to swap your carefully crafted data out for something else". in has some peculiarities, and in some cases such as where an implicit conversion might be required to make your short compatible with an in int the compiler will temporarily make an int, widen your short to it, pass it by reference and finish up. It can do this because you've declared you're not going to mess with it.


Microsoft did this with the .TryParse methods on the numeric types:

int i = 98234957;
bool success = int.TryParse("123", out i);

By flagging the parameter as out they're actively declaring here "we are definitely going to change your painstakingly crafted value of 98234957 out for something else"

Of course, they kinda have to, for things like parsing value types because if the parse method wasn't allowed to swap out the value type for something else it wouldn't work very well.. But imagine there was some fictitious method in some library you're creating:

public void PoorlyNamedMethod(out SomeClass x)

You can see it's an out, and you can thus know that if you spend hours crunching numbers, creating the perfect SomeClass:

SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);

Well that was a waste of time, taking all those hours to make that perfect class. It's definitely going to be tossed away and replaced by PoorlyNamedMethod

苏佲洛 2024-07-17 21:57:02

ref 和 out 的工作方式就像 C++ 中的引用传递和指针传递一样。

对于 ref,必须声明并初始化参数。

对于 out,必须声明参数,但可能会也可能不会初始化

        double nbr = 6; // if not initialized we get error
        double dd = doit.square(ref nbr);

        double Half_nbr ; // fine as passed by out, but inside the calling  method you initialize it
        doit.math_routines(nbr, out Half_nbr);

ref and out work just like passing by references and passing by pointers as in C++.

For ref, the argument must declared and initialized.

For out, the argument must declared but may or may not be initialized

        double nbr = 6; // if not initialized we get error
        double dd = doit.square(ref nbr);

        double Half_nbr ; // fine as passed by out, but inside the calling  method you initialize it
        doit.math_routines(nbr, out Half_nbr);
风渺 2024-07-17 21:57:02

创作时间:

(1) 我们创建调用方法 Main()

(2) 它创建一个 List 对象(这是一个引用类型对象)并将其存储在变量中我的列表

public sealed class Program 
{
    public static Main() 
    {
        List<int> myList = new List<int>();

在运行时:

(3) 运行时在堆栈上的 #00 处分配一块内存,其宽度足以存储地址 (#00 = myList,因为变量名称实际上只是 (4) 运行时在堆上的内存

位置 #FF 创建一个列表对象(所有这些地址都是为了举例)

(5) 然后运行时将对象的起始地址 #FF 存储在 #00(或用单词来说,将 List 对象的引用存储在指针 myList 中)

返回创作时间:

(6) 然后我们将 List 对象作为参数传递 myParamList到被调用方法 modifyMyList 并为其分配一个新的 List 对象

List<int> myList = new List<int>();

List<int> newList = ModifyMyList(myList)

public List<int> ModifyMyList(List<int> myParamList){
     myParamList = new List<int>();
     return myParamList;
}

在运行时:

(7) 运行时启动被调用方法的调用例程,并作为其一部分检查参数类型。

(8) 找到引用类型后,它在#04 处的堆栈上分配一块内存,用于为参数变量myParamList 别名。

(9) 然后它也将值#FF 存储在其中。

(10)运行时在堆上的内存位置#004处创建一个列表对象,并用该值替换#04中的#FF(或者在该方法中取消引用原始List对象并指向新的List对象)

#00中的地址不是更改并保留对 #FF 的引用(或原始 myList 指针不受影响)。


ref 关键字是一个编译器指令,用于跳过 (8) 和 (9) 的运行时代码的生成,这意味着方法参数不会进行堆分配。 它将使用原来的#00指针来操作#FF处的对象。 如果原始指针未初始化,运行时将停止抱怨它无法继续,因为变量未初始化

out 关键字是一个编译器指令,它几乎是与 ref 相同,但在 (9) 和 (10) 处略有修改。 编译器期望参数未初始化,并将继续执行 (8)、(4) 和 (5) 在堆上创建对象并将其起始地址存储在参数变量中。 不会抛出未初始化的错误,并且之前存储的任何引用都将丢失。

Authoring Time:

(1) We create the calling method Main()

(2) it creates a List object (which is a reference type object) and stores it in the variable myList.

public sealed class Program 
{
    public static Main() 
    {
        List<int> myList = new List<int>();

During Runtime:

(3) Runtime allocates a memory on stack at #00, wide enough to store an address (#00 = myList, since variable names are really just aliases for memory locations)

(4) Runtime creates a list object on heap at memory location #FF( all these addresses are for example sakes)

(5) Runtime would then store the starting address #FF of the object at #00(or in words, stores the reference of the List object in the pointer myList)

Back to Authoring Time:

(6) We then pass the List object as argument myParamList to the called method modifyMyList and assign a new List object to it

List<int> myList = new List<int>();

List<int> newList = ModifyMyList(myList)

public List<int> ModifyMyList(List<int> myParamList){
     myParamList = new List<int>();
     return myParamList;
}

During Runtime:

(7) Runtime starts the call routine for the called method and as part of it, checks the type of parameters.

(8) Upon finding the reference type, it allocates a memory on stack at #04 for aliasing the parameter variable myParamList.

(9) It then stores the value #FF in it as well.

(10) Runtime creates a list object on heap at memory location #004 and replaces #FF in #04 with this value(or dereferenced the original List object and pointed to the new List object in this method)

The address in #00 is not altered and retains the reference to #FF(or the original myList pointer is not disturbed).


The ref keyword is a compiler directive to skip the generation of runtime code for (8) and (9) which means there will be no heap allocation for method parameters. It will use the original #00 pointer to operate on the object at #FF. If the original pointer is not initialised, the runtime will halt complaining it can’t proceed since the variable isn’t initialised

The out keyword is a compiler directive which pretty much is the same as ref with a slight modification at (9) and (10). The compiler expects the argument to be uninitialised and will continue with (8), (4) and (5) to create an object on heap and to stores its starting address in the argument variable. No uninitialised error will be thrown and any previous reference stored will be lost.

失眠症患者 2024-07-17 21:57:02

为了说明许多出色的解释,我开发了以下控制台应用程序:

using System;
using System.Collections.Generic;

namespace CSharpDemos
{
  class Program
  {
    static void Main(string[] args)
    {
      List<string> StringList = new List<string> { "Hello" };
      List<string> StringListRef = new List<string> { "Hallo" };

      AppendWorld(StringList);
      Console.WriteLine(StringList[0] + StringList[1]);

      HalloWelt(ref StringListRef);
      Console.WriteLine(StringListRef[0] + StringListRef[1]);

      CiaoMondo(out List<string> StringListOut);
      Console.WriteLine(StringListOut[0] + StringListOut[1]);
    }

    static void AppendWorld(List<string> LiStri)
    {
      LiStri.Add(" World!");
      LiStri = new List<string> { "¡Hola", " Mundo!" };
      Console.WriteLine(LiStri[0] + LiStri[1]);
    }

    static void HalloWelt(ref List<string> LiStriRef)
     { LiStriRef = new List<string> { LiStriRef[0], " Welt!" }; }

    static void CiaoMondo(out List<string> LiStriOut)
     { LiStriOut = new List<string> { "Ciao", " Mondo!" }; }
   }
}
/*Output:
¡Hola Mundo!
Hello World!
Hallo Welt!
Ciao Mondo!
*/
  • AppendWorld:传递名为 LiStriStringList 副本。 在
    该方法开始时,此副本引用原始列表并且
    因此可用于修改此列表。 稍后的 LiStri 参考资料
    方法内的另一个 List 对象不影响
    原始列表。

  • HalloWeltLiStriRef是已初始化的别名
    ListStringRef。 传递的 List 对象用于初始化
    新的,因此 ref 是必要的。

  • CiaoMondoLiStriOutListStringOut 的别名,并且必须是
    已初始化。

因此,如果一个方法只是修改传递变量引用的对象,编译器将不允许您使用 out 并且您不应该使用 ref 因为它不会让编译器感到困惑但代码的读者。 如果该方法将使传递的参数引用另一个对象,请对已初始化的对象使用 ref ,对必须为传递的参数初始化新对象的方法使用 out 。 除此之外,refout 的行为相同。

To illustrate the many excellent explanations, I developed the following console app:

using System;
using System.Collections.Generic;

namespace CSharpDemos
{
  class Program
  {
    static void Main(string[] args)
    {
      List<string> StringList = new List<string> { "Hello" };
      List<string> StringListRef = new List<string> { "Hallo" };

      AppendWorld(StringList);
      Console.WriteLine(StringList[0] + StringList[1]);

      HalloWelt(ref StringListRef);
      Console.WriteLine(StringListRef[0] + StringListRef[1]);

      CiaoMondo(out List<string> StringListOut);
      Console.WriteLine(StringListOut[0] + StringListOut[1]);
    }

    static void AppendWorld(List<string> LiStri)
    {
      LiStri.Add(" World!");
      LiStri = new List<string> { "¡Hola", " Mundo!" };
      Console.WriteLine(LiStri[0] + LiStri[1]);
    }

    static void HalloWelt(ref List<string> LiStriRef)
     { LiStriRef = new List<string> { LiStriRef[0], " Welt!" }; }

    static void CiaoMondo(out List<string> LiStriOut)
     { LiStriOut = new List<string> { "Ciao", " Mondo!" }; }
   }
}
/*Output:
¡Hola Mundo!
Hello World!
Hallo Welt!
Ciao Mondo!
*/
  • AppendWorld: A copy of StringList named LiStri is passed. At the
    start of the method, this copy references the original list and
    therefore can be used to modify this list. Later LiStri references
    another List<string> object inside the method which doesn't affect
    the original list.

  • HalloWelt: LiStriRef is an alias of the already initialized
    ListStringRef. The passed List<string> object is used to initialize a
    new one, therefore ref was necessary.

  • CiaoMondo: LiStriOut is an alias of ListStringOut and must be
    initialized.

So, if a method just modifies the object referenced by the passed variable, the compiler will not let you use out and you should not use ref because it would confuse not the compiler but the reader of the code. If the method will make the passed argument reference another object, use ref for an already initialized object and out for methods that must initialize a new object for the passed argument. Besides that, ref and out behave the same.

独闯女儿国 2024-07-17 21:57:02

它们几乎相同 - 唯一的区别是作为 out 参数传递的变量不需要初始化,并且使用 ref 参数的方法必须将其设置为某个值。

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Ref 参数用于可能被修改的数据,out 参数用于作为已在使用某些内容的返回值的函数(例如 int.TryParse)的附加输出的数据。

They're pretty much the same - the only difference is that a variable you pass as an out parameter doesn't need to be initialised, and the method using the ref parameter has to set it to something.

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Ref parameters are for data that might be modified, out parameters are for data that's an additional output for the function (eg int.TryParse) that are already using the return value for something.

遗忘曾经 2024-07-17 21:57:02

参考:
ref 关键字用于将参数作为引用传递。 这意味着当方法中该参数的值发生更改时,它会反映在调用方法中。 使用 ref 关键字传递的参数必须在调用方法中初始化,然后再传递给被调用方法。

出去:
out 关键字也可以像 ref 关键字一样用于传递参数,但可以在不为其赋值的情况下传递参数。 使用 out 关键字传递的参数必须在返回到调用方法之前在被调用方法中初始化。

public class Example
{
 public static void Main() 
 {
 int val1 = 0; //must be initialized 
 int val2; //optional

 Example1(ref val1);
 Console.WriteLine(val1); 

 Example2(out val2);
 Console.WriteLine(val2); 
 }

 static void Example1(ref int value) 
 {
 value = 1;
 }
 static void Example2(out int value) 
 {
 value = 2; 
 }
}

/* Output     1     2     

方法重载中的 Ref 和 out

方法重载中不能同时使用 ref 和 out。 但是,ref 和 out 在运行时的处理方式不同,但在编译时的处理方式相同(CLR 在为 ref 和 out 创建 IL 时并不区分两者)。

Ref:
The ref keyword is used to pass an argument as a reference. This means that when value of that parameter is changed in the method, it gets reflected in the calling method. An argument that is passed using a ref keyword must be initialized in the calling method before it is passed to the called method.

Out:
The out keyword is also used to pass an argument like ref keyword, but the argument can be passed without assigning any value to it. An argument that is passed using an out keyword must be initialized in the called method before it returns back to calling method.

public class Example
{
 public static void Main() 
 {
 int val1 = 0; //must be initialized 
 int val2; //optional

 Example1(ref val1);
 Console.WriteLine(val1); 

 Example2(out val2);
 Console.WriteLine(val2); 
 }

 static void Example1(ref int value) 
 {
 value = 1;
 }
 static void Example2(out int value) 
 {
 value = 2; 
 }
}

/* Output     1     2     

Ref and out in method overloading

Both ref and out cannot be used in method overloading simultaneously. However, ref and out are treated differently at run-time but they are treated same at compile time (CLR doesn't differentiates between the two while it created IL for ref and out).

挽梦忆笙歌 2024-07-17 21:57:02

我想举两个主要区别:

  1. refout 通过引用传递,因此;
 class Program
    {
        public static void Main(string[] args)
        {
            var original = new ObjectWithMememberList(3);
            Console.WriteLine(original.MyList.Capacity); // 3
            ChangeList(original.MyList);
            Console.WriteLine(original.MyList.Capacity); // 3
        }

        static void ChangeList(List<int> vr)
        {
            vr = new List<int>(2);
        }
}

但是:

 class Program
    {
        public static void Main(string[] args)
        {
            var original = new ObjectWithMememberList(3);
            Console.WriteLine(original.MyList.Capacity); // 3
            ChangeList(ref original.MyList);
            Console.WriteLine(original.MyList.Capacity); // 2
        }

        static void ChangeList(ref List<int> vr)
        {
            vr = new List<int>(2);
        }
}

out 相同。
2. ref 参数必须是可赋值的变量。
嗯:

ChangeList(ref new List<int>()); // Compile Error [might not be initialized before accessing]

但是:

List<int> xs;
ChangeList(out xs); // Compiles

There 2 main difference that i want to give example for:

  1. ref and out pass by reference, hense;
 class Program
    {
        public static void Main(string[] args)
        {
            var original = new ObjectWithMememberList(3);
            Console.WriteLine(original.MyList.Capacity); // 3
            ChangeList(original.MyList);
            Console.WriteLine(original.MyList.Capacity); // 3
        }

        static void ChangeList(List<int> vr)
        {
            vr = new List<int>(2);
        }
}

but:

 class Program
    {
        public static void Main(string[] args)
        {
            var original = new ObjectWithMememberList(3);
            Console.WriteLine(original.MyList.Capacity); // 3
            ChangeList(ref original.MyList);
            Console.WriteLine(original.MyList.Capacity); // 2
        }

        static void ChangeList(ref List<int> vr)
        {
            vr = new List<int>(2);
        }
}

and same with out.
2. ref argument must be an assignable variable.
hense:

ChangeList(ref new List<int>()); // Compile Error [might not be initialized before accessing]

but:

List<int> xs;
ChangeList(out xs); // Compiles
楠木可依 2024-07-17 21:57:02

下面我展示了一个同时使用 Refout 的示例。 现在,你们都将了解裁判和出局的情况。

在下面提到的示例中,当我评论 //myRefObj = new myClass { Name = "ref external called!! " };
行,会得到一个错误,指出“使用未分配的局部变量'myRefObj'”,但out中没有这样的错误。

在哪里使用 Ref:当我们使用 in 参数调用过程时,相同的参数将用于存储该过程的输出。

在哪里使用 Out:当我们调用一个没有 in 参数的过程时,并且相同的参数将用于从该过程返回值。
另请注意输出

public partial class refAndOutUse : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        myClass myRefObj;
        myRefObj = new myClass { Name = "ref outside called!!  <br/>" };
        myRefFunction(ref myRefObj);
        Response.Write(myRefObj.Name); //ref inside function

        myClass myOutObj;
        myOutFunction(out myOutObj);
        Response.Write(myOutObj.Name); //out inside function
    }

    void myRefFunction(ref myClass refObj)
    {
        refObj.Name = "ref inside function <br/>";
        Response.Write(refObj.Name); //ref inside function
    }
    void myOutFunction(out myClass outObj)
    {
        outObj = new myClass { Name = "out inside function <br/>" }; 
        Response.Write(outObj.Name); //out inside function
    }
}

public class myClass
{
    public string Name { get; set; }
} 

Below I have shown an example using both Ref and out. Now, you all will be cleared about ref and out.

In below mentioned example when i comment //myRefObj = new myClass { Name = "ref outside called!! " };
line, will get an error saying "Use of unassigned local variable 'myRefObj'", but there is no such error in out.

Where to use Ref: when we are calling a procedure with an in parameter and the same parameter will be used to store the output of that proc.

Where to use Out: when we are calling a procedure with no in parameter and teh same param will be used to return the value from that proc.
Also note the output

public partial class refAndOutUse : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        myClass myRefObj;
        myRefObj = new myClass { Name = "ref outside called!!  <br/>" };
        myRefFunction(ref myRefObj);
        Response.Write(myRefObj.Name); //ref inside function

        myClass myOutObj;
        myOutFunction(out myOutObj);
        Response.Write(myOutObj.Name); //out inside function
    }

    void myRefFunction(ref myClass refObj)
    {
        refObj.Name = "ref inside function <br/>";
        Response.Write(refObj.Name); //ref inside function
    }
    void myOutFunction(out myClass outObj)
    {
        outObj = new myClass { Name = "out inside function <br/>" }; 
        Response.Write(outObj.Name); //out inside function
    }
}

public class myClass
{
    public string Name { get; set; }
} 
夏日浅笑〃 2024-07-17 21:57:02
 public static void Main(string[] args)
    {
        //int a=10;
        //change(ref a);
        //Console.WriteLine(a);
        // Console.Read();

        int b;
        change2(out b);
        Console.WriteLine(b);
        Console.Read();
    }
    // static void change(ref int a)
    //{
    //    a = 20;
    //}

     static void change2(out int b)
     {
         b = 20;
     }

你可以检查这个代码,它会向你描述它的完整区别
当您使用“ref”时,这意味着您已经初始化了该 int/string


当你使用“out”时
无论您是否初始化该 int/string,它都适用于两种情况
但你必须在该函数中初始化该 int/string

 public static void Main(string[] args)
    {
        //int a=10;
        //change(ref a);
        //Console.WriteLine(a);
        // Console.Read();

        int b;
        change2(out b);
        Console.WriteLine(b);
        Console.Read();
    }
    // static void change(ref int a)
    //{
    //    a = 20;
    //}

     static void change2(out int b)
     {
         b = 20;
     }

you can check this code it will describe you its complete differnce
when you use "ref" its mean that u already initialize that int/string

but
when you use "out"
it works in both conditions wheather u initialize that int/string or not
but u must initialize that int/string in that function

写给空气的情书 2024-07-17 21:57:02

从接收参数的方法的角度来看,refout 之间的区别在于 C# 要求方法必须写入每个 out 参数在返回之前,除了将其作为 out 参数传递或对其进行写入之外,不得对此类参数执行任何操作,直到将其作为 out 参数传递为止到另一种方法或直接写入。 请注意,其他一些语言没有强加这样的要求; 在 C# 中使用 out 参数声明的虚拟或接口方法可以用另一种语言覆盖,该语言不会对此类参数施加任何特殊限制。

从调用者的角度来看,C# 在许多情况下会假设调用带有 out 参数的方法时会导致传递的变量在未先读取的情况下被写入。 当调用用其他语言编写的方法时,这种假设可能不正确。 例如:

struct MyStruct
{
   ...
   myStruct(IDictionary<int, MyStruct> d)
   {
     d.TryGetValue(23, out this);
   }
}

如果 myDictionary 标识以 C# 以外的语言编写的 IDictionary 实现,即使 MyStruct s = new MyStruct(myDictionary); 看起来像一个赋值,它可能会使 s 保持不变。

请注意,与 C# 中的构造函数不同,VB.NET 中编写的构造函数不会假设调用的方法是否会修改任何 out 参数,并无条件清除所有字段。 完全用 VB 或完全用 C# 编写的代码不会发生上面提到的奇怪行为,但当用 C# 编写的代码调用用 VB.NET 编写的方法时,可能会发生。

From the standpoint of a method which receives a parameter, the difference between ref and out is that C# requires that methods must write to every out parameter before returning, and must not do anything with such a parameter, other than passing it as an out parameter or writing to it, until it has been either passed as an out parameter to another method or written directly. Note that some other languages do not impose such requirements; a virtual or interface method which is declared in C# with an out parameter may be overridden in another language which does not impose any special restrictions on such parameters.

From the standpoint of the caller, C# will in many circumstances assume when calling a method with an out parameter will cause the passed variable to be written without having been read first. This assumption may not be correct when calling methods written in other languages. For example:

struct MyStruct
{
   ...
   myStruct(IDictionary<int, MyStruct> d)
   {
     d.TryGetValue(23, out this);
   }
}

If myDictionary identifies an IDictionary<TKey,TValue> implementation written in a language other than C#, even though MyStruct s = new MyStruct(myDictionary); looks like an assignment, it could potentially leave s unmodified.

Note that constructors written in VB.NET, unlike those in C#, make no assumptions about whether called methods will modify any out parameters, and clear out all fields unconditionally. The odd behavior alluded to above won't occur with code written entirely in VB or entirely in C#, but can occur when code written in C# calls a method written in VB.NET.

娇纵 2024-07-17 21:57:02

如果你想将你的参数作为引用传递,那么你应该在将参数传递给函数之前初始化它,否则编译器本身会显示错误。但是如果是 out 参数,你不需要在将对象参数传递给函数之前初始化它。方法。您可以在调用方法本身中初始化对象。

If you want to pass your parameter as a ref then you should initialize it before passing parameter to the function else compiler itself will show the error.But in case of out parameter you don't need to initialize the object parameter before passing it to the method.You can initialize the object in the calling method itself.

绝情姑娘 2024-07-17 21:57:02

迟到的答复,但想到发帖。 可能比其他答案更清楚一些。

ref 关键字:

ref 是一个关键字,用于通过引用传递任何值(进一步了解编程中的按值调用和按引用调用)。 简而言之,您声明并初始化一个值,例如让我们说intage = 5;,因此该年龄通过保留 4 个字节的位置保存在内存中。 现在,如果您使用 ref 将这个年龄变量传递给另一个方法(这意味着通过引用而不是通过值传递它们),那么编译器将只传递该变量的引用,或者明确地说,是变量所在位置的内存地址被存储,被调用的方法接收该地址并直接访问该地址中的数据。 显然,对该数据的任何更改也会发生在调用方法中存在的变量上。

示例:我给出我的 stackoverflow 帐户的密码并告诉他
他可以做任何他想做的事,他可以提出问题或回答。 这
问题是,他所做的任何更改都会直接影响我的帐户。

Out 关键字:

Out 和 in 类似于它们都传递变量的引用。 现在我们知道两者都需要传递变量的引用,很明显,内存中必须存在一个位置来保存变量的字节。 但在 out 的情况下不会初始化。 因为要求是,被调用的方法必须初始化该值并返回它。

示例:我将 stackoverflow 站点地址发送给我的朋友并询问
他为我创建一个帐户并返回凭据。

In 关键字:

现在 in 关键字的工作方式与 ref 关键字完全相同,只有一个条件,即不得修改作为引用传递的值。

示例:我提供了我的 stackoverflow 帐户的密码,但告诉他
除了阅读或浏览网站之外,不要做任何事情。 不问任何
问题,没有答案,没有投票,什么都没有..

MSDN 参考文献:

  1. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
  2. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-修饰符
  3. https:// /learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier

希望以上内容清楚。

Late answer, but thought of posting. May be a bit more clear than the other answers.

ref keyword:

ref is a keyword which is used to pass any value by reference(refer to call by value and call by reference in programming for further knowledge). In short, you declare and initialize a value for example let us say int age = 5; so this age is saved in the memory by holding a place of 4 bytes. Now if you are passing this age variable to another method with ref (which means passing them by reference and not by value) then the compiler will just pass the reference of that variable or in clear terms, the memory address of the place where the variable is stored and the called method receives this address and directly accesses the data in that address. So obviously any change to that data will happen also to the variable present in the calling method.

Example: I give the password of my stackoverflow account and tell him
that he can do anything he wants, he can ask questions or answer. The
issue is that, any change he does will directly affect my account.

Out keyword:

Out and in are similar to that where they both pass the reference of the variable. Now we know that both need to pass the reference of the variable, it is very clear that there must be a place in memory existing that holds the bytes for the variable. But not initalized in case of out. Becuase the requirement is that, the called method must initialize the value and return it.

Example: I send the stackoverflow site address to my friend and ask
him to create an account for me and return the credentials.

In keyword:

Now in keyword works exactly the same as ref keyword with only one condition that, the value being passed as reference must not be modified.

Example: I give the password of my stackoverflow account but telll him
not to do anything except reading or surfing the site. Not to ask any
questions, no answers, no votes nothing..

MSDN References:

  1. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
  2. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
  3. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier

Hope the above is clear.

扎心 2024-07-17 21:57:02

请注意,在函数内部传递的引用参数是直接起作用的。

例如,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

这将写为 Dog,而不是 Cat。 因此你应该直接处理 someObject。

Mind well that the reference parameter which is passed inside the function is directly worked on.

For example,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

This will write Dog, not Cat. Hence you should directly work on someObject.

烟若柳尘 2024-07-17 21:57:02

我可能不太擅长这一点,但是字符串(即使它们在技术上是引用类型并且存在于堆上)肯定是按值传递的,而不是引用传递的?

        string a = "Hello";

        string b = "goodbye";

        b = a; //attempt to make b point to a, won't work.

        a = "testing";

        Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!

这就是为什么如果您希望更改存在于进行更改的函数范围之外,则需要 ref,否则您不会传递引用。

据我所知,您只需要 ref 来表示结构/值类型和字符串本身,因为字符串是一种引用类型,它假装它是但不是值类型。

不过,我可能完全错了,我是新人。

I may not be so good at this, but surely strings (even though they are technically reference types and live on the heap) are passed by value, not reference?

        string a = "Hello";

        string b = "goodbye";

        b = a; //attempt to make b point to a, won't work.

        a = "testing";

        Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!

This why you need ref if you want changes to exist outside of the scope of the function making them, you aren't passing a reference otherwise.

As far as I am aware you only need ref for structs/value types and string itself, as string is a reference type that pretends it is but is not a value type.

I could be completely wrong here though, I am new.

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