与c#中的值类型和引用类型混淆

我对参数有点困惑。 当我们必须使用引用参数时,何时应该使用c#中的方法/函数编程时使用值类型参数?

您需要非常清楚引用类型与值类型之间的区别,以及“按值”参数与“按引用”参数之间的区别。

我有关于这两个主题的文章:

  • 引用类型和值类型
  • 参数传递

当使用作为引用类型的“by value”参数时,这两者相互作用:在这种情况下,按值复制的值是引用本身; 您仍然可以修改引用引用的对象:

void SomeMethod(StringBuilder x) { x.Append("Modified"); } ... StringBuilder builder = new StringBuilder(); SomeMethod(builder); Console.WriteLine(builder.ToString()); // Writes "Modified" 

请注意,这与传递引用语义不同……如果将SomeMethod更改为包含:

 x = null; 

那么这不会使builder变量为null。 但是,如果您还将 x参数更改为ref StringBuilder x (并相应地更改了调用代码),则调用者看到对x任何更改(例如将其设置为null)。

在设计自己的API时,我强烈建议您几乎不要使用refout参数。 它们偶尔会有用,但通常它们表明你试图从单个方法返回多个值,这通常使用专门封装这些值的类型更好,或者如果你使用的话可能是Tuple类型.NET 4.当然,这条规则有例外,但这是一个很好的起点。

如果使用值类型参数,则无法在方法内更改其值(您可以但这不会反映用于调用方法的变量),而对于引用类型,您可以更改该值。

发送Value类型参数时,内部会将原始变量的副本发送到函数/方法。 因此,如果更改该函数内部的值,则变量的原始值(在声明它的函数中)将保持不变。

发送引用类型参数时,该函数直接使用该变量的原始值。 这是因为您只将该变量的内存引用发送给您的函数。

因此,根据变量的范围以及您希望如何在应用程序中使用该变量,您可以决定如何将其发送到您的函数。 一个很好的例子可能是..如果你想在你的应用程序中计算更新一些全局计数器或状态变量,那么最好通过ref发送它,以便其他函数将在以后获得该变量的最新最新值。

关于这个主题的最佳文章:

.NET中的C#堆(与)堆栈(ing):第一部分

有四个部分。

您可以尝试以下简单代码,我认为它可以帮助您更好地了解何时使用by-reference参数。

 using System.Collections.Generic; using System.Diagnostics.Contracts; class Program { static void Main(string[] args) { var list = new List(new[] { 1, 2, 3, 4 }); MakeItNull(list); Contract.Assert(list != null); MakeItRealNull(ref list); Contract.Assert(list == null); } static void MakeItNull(List list) { list = null; } static void MakeItRealNull(ref List list) { list = null; } }